2
0

appendix.adoc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. [[appendices]]
  2. = Appendices
  3. :figures: servlet/authentication/kerberos
  4. :numbered!:
  5. [appendix]
  6. == Material Used in this Document
  7. Dummy UserDetailsService used in samples because we don't have a real
  8. user source.
  9. [source,java,indent=0]
  10. ----
  11. include::example$kerberos/DummyUserDetailsService.java[tags=snippetA]
  12. ----
  13. [appendix]
  14. == Crash Course to Kerberos
  15. In any authentication process there are usually a three parties
  16. involved.
  17. image::{figures}/drawio-kerb-cc1.png[]
  18. First is a `client` which sometimes is a client computer but in most
  19. of the scenarios it is the actual user sitting on a computer and
  20. trying to access resources. Then there is the `resource` user is trying
  21. to access. In this example it is a web server.
  22. Then there is a `Key Distribution Center` or `KDC`. In a case of
  23. Windows environment this would be a `Domain Controller`. `KDC` is the
  24. one which really brings everything together and thus is the most
  25. critical component in your environment. Because of this it is also
  26. considered as a single point of failure.
  27. Initially when `Kerberos` environment is setup and domain user
  28. principals created into a database, encryption keys are also
  29. created. These encryption keys are based on shared secrets(i.e. user
  30. password) and actual passwords are never kept in a clear text.
  31. Effectively `KDC` has its own key and other keys for domain users.
  32. Interestingly there is no communication between a `resource` and a
  33. `KDC` during the authentication process.
  34. image::{figures}/drawio-kerb-cc2.png[]
  35. When client wants to authenticate itself with a `resource` it first
  36. needs to communicate with a `KDC`. `Client` will craft a special package
  37. which contains encrypted and unencrypted parts. Unencrypted part
  38. contains i.e. information about a user and encrypted part other
  39. information which is part of a protocol. `Client` will encrypt package
  40. data with its own key.
  41. When `KDC` receives this authentication package from a client it
  42. checks who this `client` claims to be from an unencrypted part and based
  43. on that information it uses `client` decryption key it already have in
  44. its database. If this decryption is succesfull `KDC` knows that this
  45. `client` is the one it claims to be.
  46. What KDC returns to a client is a ticket called `Ticket Granting
  47. Ticket` which is signed by a KDC's own private key. Later when
  48. `client` sends back this ticket it can try to decrypt it and if that
  49. operation is succesfull it knows that it was a ticket it itself
  50. originally signed and gave to a `client`.
  51. image::{figures}/drawio-kerb-cc3.png[]
  52. When client wants to get a ticket which it can use to authenticate
  53. with a service, `TGT` is sent to `KDC` which then signs a service ticket
  54. with service's own key. This a moment when a trust between
  55. `client` and `service` is created. This service ticket contains data
  56. which only `service` itself is able to decrypt.
  57. image::{figures}/drawio-kerb-cc4.png[]
  58. When `client` is authenticating with a service it sends previously
  59. received service ticket to a service which then thinks that I don't
  60. know anything about this guy but he gave me an authentication ticket.
  61. What `service` can do next is try to decrypt that ticket and if that
  62. operation is succesfull it knows that only other party who knows my
  63. credentials is the `KDC` and because I trust him I can also trust that
  64. this client is a one he claims to be.
  65. [appendix]
  66. == Setup Kerberos Environments
  67. Doing a production setup of Kerberos environment is out of scope of
  68. this document but this appendix provides some help to get you
  69. started for setting up needed components for development.
  70. [[setupmitkerberos]]
  71. === Setup MIT Kerberos
  72. First action is to setup a new realm and a database.
  73. [source,text,indent=0]
  74. ----
  75. # kdb5_util create -s -r EXAMPLE.ORG
  76. Loading random data
  77. Initializing database '/var/lib/krb5kdc/principal' for realm 'EXAMPLE.ORG',
  78. master key name 'K/M@EXAMPLE.ORG'
  79. You will be prompted for the database Master Password.
  80. It is important that you NOT FORGET this password.
  81. Enter KDC database master key:
  82. Re-enter KDC database master key to verify:
  83. ----
  84. `kadmin` command can be used to administer Kerberos environment but
  85. you can't yet use it because there are no admin users in a database.
  86. [source,text,indent=0]
  87. ----
  88. root@neo:/etc/krb5kdc# kadmin
  89. Authenticating as principal root/admin@EXAMPLE.ORG with password.
  90. kadmin: Client not found in Kerberos database while initializing
  91. kadmin interface
  92. ----
  93. Lets use `kadmin.local` command to create one.
  94. [source,text,indent=0]
  95. ----
  96. root@neo:/etc/krb5kdc# kadmin.local
  97. Authenticating as principal root/admin@EXAMPLE.ORG with password.
  98. kadmin.local: listprincs
  99. K/M@EXAMPLE.ORG
  100. kadmin/admin@EXAMPLE.ORG
  101. kadmin/changepw@EXAMPLE.ORG
  102. kadmin/cypher@EXAMPLE.ORG
  103. krbtgt/EXAMPLE.ORG@EXAMPLE.ORG
  104. kadmin.local: addprinc root/admin@EXAMPLE.ORG
  105. WARNING: no policy specified for root/admin@EXAMPLE.ORG; defaulting to
  106. no policy
  107. Enter password for principal "root/admin@EXAMPLE.ORG":
  108. Re-enter password for principal "root/admin@EXAMPLE.ORG":
  109. Principal "root/admin@EXAMPLE.ORG" created.
  110. ----
  111. Then enable admins by modifying `kadm5.acl` file and restart Kerberos
  112. services.
  113. [source,text,indent=0]
  114. ----
  115. # cat /etc/krb5kdc/kadm5.acl
  116. # This file Is the access control list for krb5 administration.
  117. */admin *
  118. ----
  119. Now you can use `kadmin` with previously created `root/admin`
  120. principal. Lets create our first user `user1`.
  121. [source,text,indent=0]
  122. ----
  123. kadmin: addprinc user1
  124. WARNING: no policy specified for user1@EXAMPLE.ORG; defaulting to no
  125. policy
  126. Enter password for principal "user1@EXAMPLE.ORG":
  127. Re-enter password for principal "user1@EXAMPLE.ORG":
  128. Principal "user1@EXAMPLE.ORG" created.
  129. ----
  130. Lets create our second user `user2` and export a keytab file.
  131. [source,text,indent=0]
  132. ----
  133. kadmin: addprinc user2
  134. WARNING: no policy specified for user2@EXAMPLE.ORG; defaulting to no
  135. policy
  136. Enter password for principal "user2@EXAMPLE.ORG":
  137. Re-enter password for principal "user2@EXAMPLE.ORG":
  138. Principal "user2@EXAMPLE.ORG" created.
  139. kadmin: ktadd -k /tmp/user2.keytab user2@EXAMPLE.ORG
  140. Entry for principal user2@EXAMPLE.ORG with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/user2.keytab.
  141. Entry for principal user2@EXAMPLE.ORG with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/user2.keytab.
  142. Entry for principal user2@EXAMPLE.ORG with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/user2.keytab.
  143. Entry for principal user2@EXAMPLE.ORG with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/user2.keytab.
  144. ----
  145. Lets create a service ticket for tomcat and export credentials to a
  146. keytab file named `tomcat.keytab`.
  147. [source,text,indent=0]
  148. ----
  149. kadmin: addprinc -randkey HTTP/neo.example.org@EXAMPLE.ORG
  150. WARNING: no policy specified for HTTP/neo.example.org@EXAMPLE.ORG;
  151. defaulting to no policy
  152. Principal "HTTP/neo.example.org@EXAMPLE.ORG" created.
  153. kadmin: ktadd -k /tmp/tomcat.keytab HTTP/neo.example.org@EXAMPLE.ORG
  154. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/tmp/tomcat2.keytab.
  155. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/tmp/tomcat2.keytab.
  156. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/tmp/tomcat2.keytab.
  157. Entry for principal HTTP/neo.example.org@EXAMPLE.ORG with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/tmp/tomcat2.keytab.
  158. ----
  159. [[setupwinkerberos]]
  160. === Setup Windows Domain Controller
  161. This was tested using `Windows Server 2012 R2`
  162. [TIP]
  163. ====
  164. Internet is full of good articles and videos how to setup Windows AD
  165. but these two are quite usefull
  166. http://www.rackspace.com/knowledge_center/article/installing-active-directory-on-windows-server-2012[Rackspace] and
  167. http://social.technet.microsoft.com/wiki/contents/articles/12370.windows-server-2012-set-up-your-first-domain-controller-step-by-step.aspx[Microsoft
  168. Technet].
  169. ====
  170. - Normal domain controller and active directory setup was done.
  171. - Used dns domain `example.org` and windows domain `EXAMPLE`.
  172. - I created various domain users like `user1`, `user2`, `user3`,
  173. `tomcat` and set passwords to `Password#`.
  174. I eventually also added all ip's of my vm's to AD's dns server for
  175. that not to cause any trouble.
  176. [source,text]
  177. ----
  178. Name: WIN-EKBO0EQ7TS7.example.org
  179. Address: 172.16.101.135
  180. Name: win8vm.example.org
  181. Address: 172.16.101.136
  182. Name: neo.example.org
  183. Address: 172.16.101.1
  184. ----
  185. Service Principal Name(SPN) needs to be setup with `HTTP` and a
  186. server name `neo.example.org` where tomcat servlet container is run. This
  187. is used with `tomcat` domain user and its `keytab` is then used as a
  188. service credential.
  189. [source,text]
  190. ----
  191. PS C:\> setspn -A HTTP/neo.example.org tomcat
  192. ----
  193. I exported keytab file which is copied to linux server running tomcat.
  194. [source,text]
  195. ----
  196. PS C:\> ktpass /out c:\tomcat.keytab /mapuser tomcat@EXAMPLE.ORG /princ HTTP/neo.example.org@EXAMPLE.ORG /pass Password# /ptype KRB5_NT_PRINCIPAL /crypto All
  197. Targeting domain controller: WIN-EKBO0EQ7TS7.example.org
  198. Using legacy password setting method
  199. Successfully mapped HTTP/neo.example.org to tomcat.
  200. ----
  201. [appendix]
  202. == Troubleshooting
  203. This appendix provides generic information about troubleshooting
  204. errors and problems.
  205. [IMPORTANT]
  206. ====
  207. If you think environment and configuration is correctly setup, do
  208. double check and ask other person to check possible obvious mistakes
  209. or typos. Kerberos setup is generally very brittle and it is not
  210. always very easy to debug where the problem lies.
  211. ====
  212. .Cannot find key of appropriate type to decrypt
  213. [source,text]
  214. ----
  215. GSSException: Failure unspecified at GSS-API level (Mechanism level:
  216. Invalid argument (400) - Cannot find key of appropriate type to
  217. decrypt AP REP - RC4 with HMAC)
  218. ----
  219. If you see abore error indicating missing key type, this will happen
  220. with two different use cases. Firstly your JVM may not support
  221. appropriate encryption type or it is disabled in your `krb5.conf`
  222. file.
  223. [source,text]
  224. ----
  225. default_tkt_enctypes = rc4-hmac
  226. default_tgs_enctypes = rc4-hmac
  227. ----
  228. Second case is less obvious and hard to track because it will lead
  229. into same error. This specific `GSSException` is throws also if you
  230. simply don't have a required encryption key which then may be caused
  231. by a misconfiguration in your kerberos server or a simply typo in your
  232. principal.
  233. .Using wrong kerberos configuration
  234. {zwsp} +
  235. In most system all commands and libraries will search kerberos
  236. configuration either from a default locations or special locations
  237. like JDKs. It's easy to get mixed up especially if working from unix
  238. systems, which already may have default settings to work with MIT
  239. kerberos, towards Windows domains.
  240. This is a specific example what happens with `ldapsearch` trying to
  241. query Windows AD using kerberos authentication.
  242. [source,text]
  243. ----
  244. $ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
  245. SASL/GSSAPI authentication started
  246. ldap_sasl_interactive_bind_s: Local error (-2)
  247. additional info: SASL(-1): generic failure: GSSAPI Error:
  248. Unspecified GSS failure. Minor code may provide more information
  249. (No Kerberos credentials available)
  250. ----
  251. Well that doesn't look good and is a simple indication that I don't
  252. have a valid kerberos tickets as shown below.
  253. [source,text]
  254. ----
  255. $ klist
  256. klist: Credentials cache file '/tmp/krb5cc_1000' not found
  257. ----
  258. We already have a keytab file we exported from Windows AD to be used
  259. with tomcat running on Linux. Lets try to use that to authenticate
  260. with Windows AD.
  261. You can have a dedicated config file which usually can be used with
  262. native Linux commands and JVMs via system propertys.
  263. [source,text]
  264. ----
  265. $ cat krb5.ini
  266. [libdefaults]
  267. default_realm = EXAMPLE.ORG
  268. default_keytab_name = /tmp/tomcat.keytab
  269. forwardable=true
  270. [realms]
  271. EXAMPLE.ORG = {
  272. kdc = WIN-EKBO0EQ7TS7.example.org:88
  273. }
  274. [domain_realm]
  275. example.org=EXAMPLE.ORG
  276. .example.org=EXAMPLE.ORG
  277. ----
  278. Lets use that config and a keytab to get initial credentials.
  279. [source,text]
  280. ----
  281. $ env KRB5_CONFIG=/path/to/krb5.ini kinit -kt tomcat.keytab HTTP/neo.example.org@EXAMPLE.ORG
  282. $ klist
  283. Ticket cache: FILE:/tmp/krb5cc_1000
  284. Default principal: HTTP/neo.example.org@EXAMPLE.ORG
  285. Valid starting Expires Service principal
  286. 26/03/15 09:04:37 26/03/15 19:04:37 krbtgt/EXAMPLE.ORG@EXAMPLE.ORG
  287. renew until 27/03/15 09:04:37
  288. ----
  289. Lets see what happens if we now try to do a simple query against
  290. Windows AD.
  291. [source,text]
  292. ----
  293. $ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
  294. SASL/GSSAPI authentication started
  295. ldap_sasl_interactive_bind_s: Local error (-2)
  296. additional info: SASL(-1): generic failure: GSSAPI Error:
  297. Unspecified GSS failure. Minor code may provide more information
  298. (KDC returned error string: PROCESS_TGS)
  299. ----
  300. This may be simply because `ldapsearch` is getting confused and simply
  301. using wrong configuration. You can tell `ldapsearch` to use a
  302. different configuration via `KRB5_CONFIG` env variable just like we
  303. did with `kinit`. You can also use `KRB5_TRACE=/dev/stderr` to get
  304. more verbose output of what native libraries are doing.
  305. [source,text]
  306. ----
  307. $ env KRB5_CONFIG=/path/to/krb5.ini ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org -b "dc=example,dc=org"
  308. $ klist
  309. Ticket cache: FILE:/tmp/krb5cc_1000
  310. Default principal: HTTP/neo.example.org@EXAMPLE.ORG
  311. Valid starting Expires Service principal
  312. 26/03/15 09:11:03 26/03/15 19:11:03 krbtgt/EXAMPLE.ORG@EXAMPLE.ORG
  313. renew until 27/03/15 09:11:03
  314. 26/03/15 09:11:44 26/03/15 19:11:03
  315. ldap/win-ekbo0eq7ts7.example.org@EXAMPLE.ORG
  316. renew until 27/03/15 09:11:03
  317. ----
  318. Above you can see what happened if query was successful by looking
  319. kerberos tickets. Now you can experiment with further query commands
  320. i.e. if you working with `KerberosLdapContextSource`.
  321. [source,text]
  322. ----
  323. $ ldapsearch -H ldap://WIN-EKBO0EQ7TS7.example.org \
  324. -b "dc=example,dc=org" \
  325. "(| (userPrincipalName=user2@EXAMPLE.ORG)
  326. (sAMAccountName=user2@EXAMPLE.ORG))" \
  327. dn
  328. ...
  329. # test user, example.org
  330. dn: CN=test user,DC=example,DC=org
  331. ----
  332. [appendix]
  333. [[browserspnegoconfig]]
  334. == Configure Browsers for Spnego Negotiation
  335. === Firefox
  336. Complete following steps to ensure that your Firefox browser is
  337. enabled to perform Spnego authentication.
  338. - Open Firefox.
  339. - At address field, type *about:config*.
  340. - In filter/search, type *negotiate*.
  341. - Parameter *network.negotiate-auth.trusted-uris* may be set to
  342. default *https://* which doesn't work for you. Generally speaking
  343. this parameter has to replaced with the server address if Kerberos
  344. delegation is required.
  345. - It is recommended to use `https` for all communication.
  346. === Chrome
  347. With Google Chrome you generally need to set command-line parameters
  348. order to white list servers with Chrome will negotiate.
  349. - on Windows machines (clients): Chrome shares the configuration with
  350. Internet Explorer so if all changes were applied to IE (as described
  351. in E.3), nothing has to be passed via command-line parameters.
  352. - on Linux/Mac OS machines (clients): the command-line parameter
  353. `--auth-negotiate-delegate-whitelist` should only used if Kerberos
  354. delegation is required (otherwise do not set this parameter).
  355. - It is recommended to use `https` for all communication.
  356. [source,text]
  357. ----
  358. --auth-server-whitelist="*.example.com"
  359. --auth-negotiate-delegate-whitelist="*.example.com"
  360. ----
  361. You can see which policies are enable by typing *chrome://policy/*
  362. into Chrome's address bar.
  363. With Linux Chrome will also read policy files from
  364. `/etc/opt/chrome/policies/managed` directory.
  365. .mypolicy.json
  366. [source,json]
  367. ----
  368. {
  369. "AuthServerWhitelist" : "*.example.org",
  370. "AuthNegotiateDelegateWhitelist" : "*.example.org",
  371. "DisableAuthNegotiateCnameLookup" : true,
  372. "EnableAuthNegotiatePort" : true
  373. }
  374. ----
  375. === Internet Explorer
  376. Complete following steps to ensure that your Internet Explorer browser
  377. is enabled to perform Spnego authentication.
  378. - Open Internet Explorer.
  379. - Click *Tools > Intenet Options > Security* tab.
  380. - In *Local intranet* section make sure your server is trusted by i.e.
  381. adding it into a list.