You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1358 lines
34 KiB

  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cmd
  5. import (
  6. "testing"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/modules/auth/ldap"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/urfave/cli"
  11. )
  12. func TestAddLdapBindDn(t *testing.T) {
  13. // Mock cli functions to do not exit on error
  14. var osExiter = cli.OsExiter
  15. defer func() { cli.OsExiter = osExiter }()
  16. cli.OsExiter = func(code int) {}
  17. // Test cases
  18. var cases = []struct {
  19. args []string
  20. loginSource *models.LoginSource
  21. errMsg string
  22. }{
  23. // case 0
  24. {
  25. args: []string{
  26. "ldap-test",
  27. "--name", "ldap (via Bind DN) source full",
  28. "--not-active",
  29. "--security-protocol", "ldaps",
  30. "--skip-tls-verify",
  31. "--host", "ldap-bind-server full",
  32. "--port", "9876",
  33. "--user-search-base", "ou=Users,dc=full-domain-bind,dc=org",
  34. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
  35. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
  36. "--restricted-filter", "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
  37. "--username-attribute", "uid-bind full",
  38. "--firstname-attribute", "givenName-bind full",
  39. "--surname-attribute", "sn-bind full",
  40. "--email-attribute", "mail-bind full",
  41. "--public-ssh-key-attribute", "publickey-bind full",
  42. "--bind-dn", "cn=readonly,dc=full-domain-bind,dc=org",
  43. "--bind-password", "secret-bind-full",
  44. "--attributes-in-bind",
  45. "--synchronize-users",
  46. "--page-size", "99",
  47. },
  48. loginSource: &models.LoginSource{
  49. Type: models.LoginLDAP,
  50. Name: "ldap (via Bind DN) source full",
  51. IsActived: false,
  52. IsSyncEnabled: true,
  53. Cfg: &models.LDAPConfig{
  54. Source: &ldap.Source{
  55. Name: "ldap (via Bind DN) source full",
  56. Host: "ldap-bind-server full",
  57. Port: 9876,
  58. SecurityProtocol: ldap.SecurityProtocol(1),
  59. SkipVerify: true,
  60. BindDN: "cn=readonly,dc=full-domain-bind,dc=org",
  61. BindPassword: "secret-bind-full",
  62. UserBase: "ou=Users,dc=full-domain-bind,dc=org",
  63. AttributeUsername: "uid-bind full",
  64. AttributeName: "givenName-bind full",
  65. AttributeSurname: "sn-bind full",
  66. AttributeMail: "mail-bind full",
  67. AttributesInBind: true,
  68. AttributeSSHPublicKey: "publickey-bind full",
  69. SearchPageSize: 99,
  70. Filter: "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
  71. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
  72. RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
  73. Enabled: true,
  74. },
  75. },
  76. },
  77. },
  78. // case 1
  79. {
  80. args: []string{
  81. "ldap-test",
  82. "--name", "ldap (via Bind DN) source min",
  83. "--security-protocol", "unencrypted",
  84. "--host", "ldap-bind-server min",
  85. "--port", "1234",
  86. "--user-search-base", "ou=Users,dc=min-domain-bind,dc=org",
  87. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=min-domain-bind,dc=org)",
  88. "--email-attribute", "mail-bind min",
  89. },
  90. loginSource: &models.LoginSource{
  91. Type: models.LoginLDAP,
  92. Name: "ldap (via Bind DN) source min",
  93. IsActived: true,
  94. Cfg: &models.LDAPConfig{
  95. Source: &ldap.Source{
  96. Name: "ldap (via Bind DN) source min",
  97. Host: "ldap-bind-server min",
  98. Port: 1234,
  99. SecurityProtocol: ldap.SecurityProtocol(0),
  100. UserBase: "ou=Users,dc=min-domain-bind,dc=org",
  101. AttributeMail: "mail-bind min",
  102. Filter: "(memberOf=cn=user-group,ou=example,dc=min-domain-bind,dc=org)",
  103. Enabled: true,
  104. },
  105. },
  106. },
  107. },
  108. // case 2
  109. {
  110. args: []string{
  111. "ldap-test",
  112. "--name", "ldap (via Bind DN) source",
  113. "--security-protocol", "zzzzz",
  114. "--host", "ldap-server",
  115. "--port", "1234",
  116. "--user-search-base", "ou=Users,dc=domain,dc=org",
  117. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  118. "--email-attribute", "mail",
  119. },
  120. errMsg: "Unknown security protocol name: zzzzz",
  121. },
  122. // case 3
  123. {
  124. args: []string{
  125. "ldap-test",
  126. "--security-protocol", "unencrypted",
  127. "--host", "ldap-server",
  128. "--port", "1234",
  129. "--user-search-base", "ou=Users,dc=domain,dc=org",
  130. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  131. "--email-attribute", "mail",
  132. },
  133. errMsg: "name is not set",
  134. },
  135. // case 4
  136. {
  137. args: []string{
  138. "ldap-test",
  139. "--name", "ldap (via Bind DN) source",
  140. "--host", "ldap-server",
  141. "--port", "1234",
  142. "--user-search-base", "ou=Users,dc=domain,dc=org",
  143. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  144. "--email-attribute", "mail",
  145. },
  146. errMsg: "security-protocol is not set",
  147. },
  148. // case 5
  149. {
  150. args: []string{
  151. "ldap-test",
  152. "--name", "ldap (via Bind DN) source",
  153. "--security-protocol", "unencrypted",
  154. "--port", "1234",
  155. "--user-search-base", "ou=Users,dc=domain,dc=org",
  156. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  157. "--email-attribute", "mail",
  158. },
  159. errMsg: "host is not set",
  160. },
  161. // case 6
  162. {
  163. args: []string{
  164. "ldap-test",
  165. "--name", "ldap (via Bind DN) source",
  166. "--security-protocol", "unencrypted",
  167. "--host", "ldap-server",
  168. "--user-search-base", "ou=Users,dc=domain,dc=org",
  169. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  170. "--email-attribute", "mail",
  171. },
  172. errMsg: "port is not set",
  173. },
  174. // case 7
  175. {
  176. args: []string{
  177. "ldap-test",
  178. "--name", "ldap (via Bind DN) source",
  179. "--security-protocol", "unencrypted",
  180. "--host", "ldap-server",
  181. "--port", "1234",
  182. "--user-search-base", "ou=Users,dc=domain,dc=org",
  183. "--email-attribute", "mail",
  184. },
  185. errMsg: "user-filter is not set",
  186. },
  187. // case 8
  188. {
  189. args: []string{
  190. "ldap-test",
  191. "--name", "ldap (via Bind DN) source",
  192. "--security-protocol", "unencrypted",
  193. "--host", "ldap-server",
  194. "--port", "1234",
  195. "--user-search-base", "ou=Users,dc=domain,dc=org",
  196. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  197. },
  198. errMsg: "email-attribute is not set",
  199. },
  200. }
  201. for n, c := range cases {
  202. // Mock functions.
  203. var createdLoginSource *models.LoginSource
  204. service := &authService{
  205. initDB: func() error {
  206. return nil
  207. },
  208. createLoginSource: func(loginSource *models.LoginSource) error {
  209. createdLoginSource = loginSource
  210. return nil
  211. },
  212. updateLoginSource: func(loginSource *models.LoginSource) error {
  213. assert.FailNow(t, "case %d: should not call updateLoginSource", n)
  214. return nil
  215. },
  216. getLoginSourceByID: func(id int64) (*models.LoginSource, error) {
  217. assert.FailNow(t, "case %d: should not call getLoginSourceByID", n)
  218. return nil, nil
  219. },
  220. }
  221. // Create a copy of command to test
  222. app := cli.NewApp()
  223. app.Flags = cmdAuthAddLdapBindDn.Flags
  224. app.Action = service.addLdapBindDn
  225. // Run it
  226. err := app.Run(c.args)
  227. if c.errMsg != "" {
  228. assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
  229. } else {
  230. assert.NoError(t, err, "case %d: should have no errors", n)
  231. assert.Equal(t, c.loginSource, createdLoginSource, "case %d: wrong loginSource", n)
  232. }
  233. }
  234. }
  235. func TestAddLdapSimpleAuth(t *testing.T) {
  236. // Mock cli functions to do not exit on error
  237. var osExiter = cli.OsExiter
  238. defer func() { cli.OsExiter = osExiter }()
  239. cli.OsExiter = func(code int) {}
  240. // Test cases
  241. var cases = []struct {
  242. args []string
  243. loginSource *models.LoginSource
  244. errMsg string
  245. }{
  246. // case 0
  247. {
  248. args: []string{
  249. "ldap-test",
  250. "--name", "ldap (simple auth) source full",
  251. "--not-active",
  252. "--security-protocol", "starttls",
  253. "--skip-tls-verify",
  254. "--host", "ldap-simple-server full",
  255. "--port", "987",
  256. "--user-search-base", "ou=Users,dc=full-domain-simple,dc=org",
  257. "--user-filter", "(&(objectClass=posixAccount)(full-simple-cn=%s))",
  258. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
  259. "--restricted-filter", "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",
  260. "--username-attribute", "uid-simple full",
  261. "--firstname-attribute", "givenName-simple full",
  262. "--surname-attribute", "sn-simple full",
  263. "--email-attribute", "mail-simple full",
  264. "--public-ssh-key-attribute", "publickey-simple full",
  265. "--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
  266. },
  267. loginSource: &models.LoginSource{
  268. Type: models.LoginDLDAP,
  269. Name: "ldap (simple auth) source full",
  270. IsActived: false,
  271. Cfg: &models.LDAPConfig{
  272. Source: &ldap.Source{
  273. Name: "ldap (simple auth) source full",
  274. Host: "ldap-simple-server full",
  275. Port: 987,
  276. SecurityProtocol: ldap.SecurityProtocol(2),
  277. SkipVerify: true,
  278. UserDN: "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
  279. UserBase: "ou=Users,dc=full-domain-simple,dc=org",
  280. AttributeUsername: "uid-simple full",
  281. AttributeName: "givenName-simple full",
  282. AttributeSurname: "sn-simple full",
  283. AttributeMail: "mail-simple full",
  284. AttributeSSHPublicKey: "publickey-simple full",
  285. Filter: "(&(objectClass=posixAccount)(full-simple-cn=%s))",
  286. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
  287. RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",
  288. Enabled: true,
  289. },
  290. },
  291. },
  292. },
  293. // case 1
  294. {
  295. args: []string{
  296. "ldap-test",
  297. "--name", "ldap (simple auth) source min",
  298. "--security-protocol", "unencrypted",
  299. "--host", "ldap-simple-server min",
  300. "--port", "123",
  301. "--user-filter", "(&(objectClass=posixAccount)(min-simple-cn=%s))",
  302. "--email-attribute", "mail-simple min",
  303. "--user-dn", "cn=%s,ou=Users,dc=min-domain-simple,dc=org",
  304. },
  305. loginSource: &models.LoginSource{
  306. Type: models.LoginDLDAP,
  307. Name: "ldap (simple auth) source min",
  308. IsActived: true,
  309. Cfg: &models.LDAPConfig{
  310. Source: &ldap.Source{
  311. Name: "ldap (simple auth) source min",
  312. Host: "ldap-simple-server min",
  313. Port: 123,
  314. SecurityProtocol: ldap.SecurityProtocol(0),
  315. UserDN: "cn=%s,ou=Users,dc=min-domain-simple,dc=org",
  316. AttributeMail: "mail-simple min",
  317. Filter: "(&(objectClass=posixAccount)(min-simple-cn=%s))",
  318. Enabled: true,
  319. },
  320. },
  321. },
  322. },
  323. // case 2
  324. {
  325. args: []string{
  326. "ldap-test",
  327. "--name", "ldap (simple auth) source",
  328. "--security-protocol", "zzzzz",
  329. "--host", "ldap-server",
  330. "--port", "123",
  331. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  332. "--email-attribute", "mail",
  333. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  334. },
  335. errMsg: "Unknown security protocol name: zzzzz",
  336. },
  337. // case 3
  338. {
  339. args: []string{
  340. "ldap-test",
  341. "--security-protocol", "unencrypted",
  342. "--host", "ldap-server",
  343. "--port", "123",
  344. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  345. "--email-attribute", "mail",
  346. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  347. },
  348. errMsg: "name is not set",
  349. },
  350. // case 4
  351. {
  352. args: []string{
  353. "ldap-test",
  354. "--name", "ldap (simple auth) source",
  355. "--host", "ldap-server",
  356. "--port", "123",
  357. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  358. "--email-attribute", "mail",
  359. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  360. },
  361. errMsg: "security-protocol is not set",
  362. },
  363. // case 5
  364. {
  365. args: []string{
  366. "ldap-test",
  367. "--name", "ldap (simple auth) source",
  368. "--security-protocol", "unencrypted",
  369. "--port", "123",
  370. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  371. "--email-attribute", "mail",
  372. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  373. },
  374. errMsg: "host is not set",
  375. },
  376. // case 6
  377. {
  378. args: []string{
  379. "ldap-test",
  380. "--name", "ldap (simple auth) source",
  381. "--security-protocol", "unencrypted",
  382. "--host", "ldap-server",
  383. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  384. "--email-attribute", "mail",
  385. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  386. },
  387. errMsg: "port is not set",
  388. },
  389. // case 7
  390. {
  391. args: []string{
  392. "ldap-test",
  393. "--name", "ldap (simple auth) source",
  394. "--security-protocol", "unencrypted",
  395. "--host", "ldap-server",
  396. "--port", "123",
  397. "--email-attribute", "mail",
  398. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  399. },
  400. errMsg: "user-filter is not set",
  401. },
  402. // case 8
  403. {
  404. args: []string{
  405. "ldap-test",
  406. "--name", "ldap (simple auth) source",
  407. "--security-protocol", "unencrypted",
  408. "--host", "ldap-server",
  409. "--port", "123",
  410. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  411. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  412. },
  413. errMsg: "email-attribute is not set",
  414. },
  415. // case 9
  416. {
  417. args: []string{
  418. "ldap-test",
  419. "--name", "ldap (simple auth) source",
  420. "--security-protocol", "unencrypted",
  421. "--host", "ldap-server",
  422. "--port", "123",
  423. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  424. "--email-attribute", "mail",
  425. },
  426. errMsg: "user-dn is not set",
  427. },
  428. }
  429. for n, c := range cases {
  430. // Mock functions.
  431. var createdLoginSource *models.LoginSource
  432. service := &authService{
  433. initDB: func() error {
  434. return nil
  435. },
  436. createLoginSource: func(loginSource *models.LoginSource) error {
  437. createdLoginSource = loginSource
  438. return nil
  439. },
  440. updateLoginSource: func(loginSource *models.LoginSource) error {
  441. assert.FailNow(t, "case %d: should not call updateLoginSource", n)
  442. return nil
  443. },
  444. getLoginSourceByID: func(id int64) (*models.LoginSource, error) {
  445. assert.FailNow(t, "case %d: should not call getLoginSourceByID", n)
  446. return nil, nil
  447. },
  448. }
  449. // Create a copy of command to test
  450. app := cli.NewApp()
  451. app.Flags = cmdAuthAddLdapSimpleAuth.Flags
  452. app.Action = service.addLdapSimpleAuth
  453. // Run it
  454. err := app.Run(c.args)
  455. if c.errMsg != "" {
  456. assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
  457. } else {
  458. assert.NoError(t, err, "case %d: should have no errors", n)
  459. assert.Equal(t, c.loginSource, createdLoginSource, "case %d: wrong loginSource", n)
  460. }
  461. }
  462. }
  463. func TestUpdateLdapBindDn(t *testing.T) {
  464. // Mock cli functions to do not exit on error
  465. var osExiter = cli.OsExiter
  466. defer func() { cli.OsExiter = osExiter }()
  467. cli.OsExiter = func(code int) {}
  468. // Test cases
  469. var cases = []struct {
  470. args []string
  471. id int64
  472. existingLoginSource *models.LoginSource
  473. loginSource *models.LoginSource
  474. errMsg string
  475. }{
  476. // case 0
  477. {
  478. args: []string{
  479. "ldap-test",
  480. "--id", "23",
  481. "--name", "ldap (via Bind DN) source full",
  482. "--not-active",
  483. "--security-protocol", "LDAPS",
  484. "--skip-tls-verify",
  485. "--host", "ldap-bind-server full",
  486. "--port", "9876",
  487. "--user-search-base", "ou=Users,dc=full-domain-bind,dc=org",
  488. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
  489. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
  490. "--restricted-filter", "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
  491. "--username-attribute", "uid-bind full",
  492. "--firstname-attribute", "givenName-bind full",
  493. "--surname-attribute", "sn-bind full",
  494. "--email-attribute", "mail-bind full",
  495. "--public-ssh-key-attribute", "publickey-bind full",
  496. "--bind-dn", "cn=readonly,dc=full-domain-bind,dc=org",
  497. "--bind-password", "secret-bind-full",
  498. "--synchronize-users",
  499. "--page-size", "99",
  500. },
  501. id: 23,
  502. existingLoginSource: &models.LoginSource{
  503. Type: models.LoginLDAP,
  504. IsActived: true,
  505. Cfg: &models.LDAPConfig{
  506. Source: &ldap.Source{
  507. Enabled: true,
  508. },
  509. },
  510. },
  511. loginSource: &models.LoginSource{
  512. Type: models.LoginLDAP,
  513. Name: "ldap (via Bind DN) source full",
  514. IsActived: false,
  515. IsSyncEnabled: true,
  516. Cfg: &models.LDAPConfig{
  517. Source: &ldap.Source{
  518. Name: "ldap (via Bind DN) source full",
  519. Host: "ldap-bind-server full",
  520. Port: 9876,
  521. SecurityProtocol: ldap.SecurityProtocol(1),
  522. SkipVerify: true,
  523. BindDN: "cn=readonly,dc=full-domain-bind,dc=org",
  524. BindPassword: "secret-bind-full",
  525. UserBase: "ou=Users,dc=full-domain-bind,dc=org",
  526. AttributeUsername: "uid-bind full",
  527. AttributeName: "givenName-bind full",
  528. AttributeSurname: "sn-bind full",
  529. AttributeMail: "mail-bind full",
  530. AttributesInBind: false,
  531. AttributeSSHPublicKey: "publickey-bind full",
  532. SearchPageSize: 99,
  533. Filter: "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
  534. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
  535. RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
  536. Enabled: true,
  537. },
  538. },
  539. },
  540. },
  541. // case 1
  542. {
  543. args: []string{
  544. "ldap-test",
  545. "--id", "1",
  546. },
  547. loginSource: &models.LoginSource{
  548. Type: models.LoginLDAP,
  549. Cfg: &models.LDAPConfig{
  550. Source: &ldap.Source{},
  551. },
  552. },
  553. },
  554. // case 2
  555. {
  556. args: []string{
  557. "ldap-test",
  558. "--id", "1",
  559. "--name", "ldap (via Bind DN) source",
  560. },
  561. loginSource: &models.LoginSource{
  562. Type: models.LoginLDAP,
  563. Name: "ldap (via Bind DN) source",
  564. Cfg: &models.LDAPConfig{
  565. Source: &ldap.Source{
  566. Name: "ldap (via Bind DN) source",
  567. },
  568. },
  569. },
  570. },
  571. // case 3
  572. {
  573. args: []string{
  574. "ldap-test",
  575. "--id", "1",
  576. "--not-active",
  577. },
  578. existingLoginSource: &models.LoginSource{
  579. Type: models.LoginLDAP,
  580. IsActived: true,
  581. Cfg: &models.LDAPConfig{
  582. Source: &ldap.Source{},
  583. },
  584. },
  585. loginSource: &models.LoginSource{
  586. Type: models.LoginLDAP,
  587. IsActived: false,
  588. Cfg: &models.LDAPConfig{
  589. Source: &ldap.Source{},
  590. },
  591. },
  592. },
  593. // case 4
  594. {
  595. args: []string{
  596. "ldap-test",
  597. "--id", "1",
  598. "--security-protocol", "LDAPS",
  599. },
  600. loginSource: &models.LoginSource{
  601. Type: models.LoginLDAP,
  602. Cfg: &models.LDAPConfig{
  603. Source: &ldap.Source{
  604. SecurityProtocol: ldap.SecurityProtocol(1),
  605. },
  606. },
  607. },
  608. },
  609. // case 5
  610. {
  611. args: []string{
  612. "ldap-test",
  613. "--id", "1",
  614. "--skip-tls-verify",
  615. },
  616. loginSource: &models.LoginSource{
  617. Type: models.LoginLDAP,
  618. Cfg: &models.LDAPConfig{
  619. Source: &ldap.Source{
  620. SkipVerify: true,
  621. },
  622. },
  623. },
  624. },
  625. // case 6
  626. {
  627. args: []string{
  628. "ldap-test",
  629. "--id", "1",
  630. "--host", "ldap-server",
  631. },
  632. loginSource: &models.LoginSource{
  633. Type: models.LoginLDAP,
  634. Cfg: &models.LDAPConfig{
  635. Source: &ldap.Source{
  636. Host: "ldap-server",
  637. },
  638. },
  639. },
  640. },
  641. // case 7
  642. {
  643. args: []string{
  644. "ldap-test",
  645. "--id", "1",
  646. "--port", "389",
  647. },
  648. loginSource: &models.LoginSource{
  649. Type: models.LoginLDAP,
  650. Cfg: &models.LDAPConfig{
  651. Source: &ldap.Source{
  652. Port: 389,
  653. },
  654. },
  655. },
  656. },
  657. // case 8
  658. {
  659. args: []string{
  660. "ldap-test",
  661. "--id", "1",
  662. "--user-search-base", "ou=Users,dc=domain,dc=org",
  663. },
  664. loginSource: &models.LoginSource{
  665. Type: models.LoginLDAP,
  666. Cfg: &models.LDAPConfig{
  667. Source: &ldap.Source{
  668. UserBase: "ou=Users,dc=domain,dc=org",
  669. },
  670. },
  671. },
  672. },
  673. // case 9
  674. {
  675. args: []string{
  676. "ldap-test",
  677. "--id", "1",
  678. "--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  679. },
  680. loginSource: &models.LoginSource{
  681. Type: models.LoginLDAP,
  682. Cfg: &models.LDAPConfig{
  683. Source: &ldap.Source{
  684. Filter: "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
  685. },
  686. },
  687. },
  688. },
  689. // case 10
  690. {
  691. args: []string{
  692. "ldap-test",
  693. "--id", "1",
  694. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=domain,dc=org)",
  695. },
  696. loginSource: &models.LoginSource{
  697. Type: models.LoginLDAP,
  698. Cfg: &models.LDAPConfig{
  699. Source: &ldap.Source{
  700. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=domain,dc=org)",
  701. },
  702. },
  703. },
  704. },
  705. // case 11
  706. {
  707. args: []string{
  708. "ldap-test",
  709. "--id", "1",
  710. "--username-attribute", "uid",
  711. },
  712. loginSource: &models.LoginSource{
  713. Type: models.LoginLDAP,
  714. Cfg: &models.LDAPConfig{
  715. Source: &ldap.Source{
  716. AttributeUsername: "uid",
  717. },
  718. },
  719. },
  720. },
  721. // case 12
  722. {
  723. args: []string{
  724. "ldap-test",
  725. "--id", "1",
  726. "--firstname-attribute", "givenName",
  727. },
  728. loginSource: &models.LoginSource{
  729. Type: models.LoginLDAP,
  730. Cfg: &models.LDAPConfig{
  731. Source: &ldap.Source{
  732. AttributeName: "givenName",
  733. },
  734. },
  735. },
  736. },
  737. // case 13
  738. {
  739. args: []string{
  740. "ldap-test",
  741. "--id", "1",
  742. "--surname-attribute", "sn",
  743. },
  744. loginSource: &models.LoginSource{
  745. Type: models.LoginLDAP,
  746. Cfg: &models.LDAPConfig{
  747. Source: &ldap.Source{
  748. AttributeSurname: "sn",
  749. },
  750. },
  751. },
  752. },
  753. // case 14
  754. {
  755. args: []string{
  756. "ldap-test",
  757. "--id", "1",
  758. "--email-attribute", "mail",
  759. },
  760. loginSource: &models.LoginSource{
  761. Type: models.LoginLDAP,
  762. Cfg: &models.LDAPConfig{
  763. Source: &ldap.Source{
  764. AttributeMail: "mail",
  765. },
  766. },
  767. },
  768. },
  769. // case 15
  770. {
  771. args: []string{
  772. "ldap-test",
  773. "--id", "1",
  774. "--attributes-in-bind",
  775. },
  776. loginSource: &models.LoginSource{
  777. Type: models.LoginLDAP,
  778. Cfg: &models.LDAPConfig{
  779. Source: &ldap.Source{
  780. AttributesInBind: true,
  781. },
  782. },
  783. },
  784. },
  785. // case 16
  786. {
  787. args: []string{
  788. "ldap-test",
  789. "--id", "1",
  790. "--public-ssh-key-attribute", "publickey",
  791. },
  792. loginSource: &models.LoginSource{
  793. Type: models.LoginLDAP,
  794. Cfg: &models.LDAPConfig{
  795. Source: &ldap.Source{
  796. AttributeSSHPublicKey: "publickey",
  797. },
  798. },
  799. },
  800. },
  801. // case 17
  802. {
  803. args: []string{
  804. "ldap-test",
  805. "--id", "1",
  806. "--bind-dn", "cn=readonly,dc=domain,dc=org",
  807. },
  808. loginSource: &models.LoginSource{
  809. Type: models.LoginLDAP,
  810. Cfg: &models.LDAPConfig{
  811. Source: &ldap.Source{
  812. BindDN: "cn=readonly,dc=domain,dc=org",
  813. },
  814. },
  815. },
  816. },
  817. // case 18
  818. {
  819. args: []string{
  820. "ldap-test",
  821. "--id", "1",
  822. "--bind-password", "secret",
  823. },
  824. loginSource: &models.LoginSource{
  825. Type: models.LoginLDAP,
  826. Cfg: &models.LDAPConfig{
  827. Source: &ldap.Source{
  828. BindPassword: "secret",
  829. },
  830. },
  831. },
  832. },
  833. // case 19
  834. {
  835. args: []string{
  836. "ldap-test",
  837. "--id", "1",
  838. "--synchronize-users",
  839. },
  840. loginSource: &models.LoginSource{
  841. Type: models.LoginLDAP,
  842. IsSyncEnabled: true,
  843. Cfg: &models.LDAPConfig{
  844. Source: &ldap.Source{},
  845. },
  846. },
  847. },
  848. // case 20
  849. {
  850. args: []string{
  851. "ldap-test",
  852. "--id", "1",
  853. "--page-size", "12",
  854. },
  855. loginSource: &models.LoginSource{
  856. Type: models.LoginLDAP,
  857. Cfg: &models.LDAPConfig{
  858. Source: &ldap.Source{
  859. SearchPageSize: 12,
  860. },
  861. },
  862. },
  863. },
  864. // case 21
  865. {
  866. args: []string{
  867. "ldap-test",
  868. "--id", "1",
  869. "--security-protocol", "xxxxx",
  870. },
  871. errMsg: "Unknown security protocol name: xxxxx",
  872. },
  873. // case 22
  874. {
  875. args: []string{
  876. "ldap-test",
  877. },
  878. errMsg: "id is not set",
  879. },
  880. // case 23
  881. {
  882. args: []string{
  883. "ldap-test",
  884. "--id", "1",
  885. },
  886. existingLoginSource: &models.LoginSource{
  887. Type: models.LoginOAuth2,
  888. Cfg: &models.LDAPConfig{
  889. Source: &ldap.Source{},
  890. },
  891. },
  892. errMsg: "Invalid authentication type. expected: LDAP (via BindDN), actual: OAuth2",
  893. },
  894. }
  895. for n, c := range cases {
  896. // Mock functions.
  897. var updatedLoginSource *models.LoginSource
  898. service := &authService{
  899. initDB: func() error {
  900. return nil
  901. },
  902. createLoginSource: func(loginSource *models.LoginSource) error {
  903. assert.FailNow(t, "case %d: should not call createLoginSource", n)
  904. return nil
  905. },
  906. updateLoginSource: func(loginSource *models.LoginSource) error {
  907. updatedLoginSource = loginSource
  908. return nil
  909. },
  910. getLoginSourceByID: func(id int64) (*models.LoginSource, error) {
  911. if c.id != 0 {
  912. assert.Equal(t, c.id, id, "case %d: wrong id", n)
  913. }
  914. if c.existingLoginSource != nil {
  915. return c.existingLoginSource, nil
  916. }
  917. return &models.LoginSource{
  918. Type: models.LoginLDAP,
  919. Cfg: &models.LDAPConfig{
  920. Source: &ldap.Source{},
  921. },
  922. }, nil
  923. },
  924. }
  925. // Create a copy of command to test
  926. app := cli.NewApp()
  927. app.Flags = cmdAuthUpdateLdapBindDn.Flags
  928. app.Action = service.updateLdapBindDn
  929. // Run it
  930. err := app.Run(c.args)
  931. if c.errMsg != "" {
  932. assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
  933. } else {
  934. assert.NoError(t, err, "case %d: should have no errors", n)
  935. assert.Equal(t, c.loginSource, updatedLoginSource, "case %d: wrong loginSource", n)
  936. }
  937. }
  938. }
  939. func TestUpdateLdapSimpleAuth(t *testing.T) {
  940. // Mock cli functions to do not exit on error
  941. var osExiter = cli.OsExiter
  942. defer func() { cli.OsExiter = osExiter }()
  943. cli.OsExiter = func(code int) {}
  944. // Test cases
  945. var cases = []struct {
  946. args []string
  947. id int64
  948. existingLoginSource *models.LoginSource
  949. loginSource *models.LoginSource
  950. errMsg string
  951. }{
  952. // case 0
  953. {
  954. args: []string{
  955. "ldap-test",
  956. "--id", "7",
  957. "--name", "ldap (simple auth) source full",
  958. "--not-active",
  959. "--security-protocol", "starttls",
  960. "--skip-tls-verify",
  961. "--host", "ldap-simple-server full",
  962. "--port", "987",
  963. "--user-search-base", "ou=Users,dc=full-domain-simple,dc=org",
  964. "--user-filter", "(&(objectClass=posixAccount)(full-simple-cn=%s))",
  965. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
  966. "--restricted-filter", "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",
  967. "--username-attribute", "uid-simple full",
  968. "--firstname-attribute", "givenName-simple full",
  969. "--surname-attribute", "sn-simple full",
  970. "--email-attribute", "mail-simple full",
  971. "--public-ssh-key-attribute", "publickey-simple full",
  972. "--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
  973. },
  974. id: 7,
  975. loginSource: &models.LoginSource{
  976. Type: models.LoginDLDAP,
  977. Name: "ldap (simple auth) source full",
  978. IsActived: false,
  979. Cfg: &models.LDAPConfig{
  980. Source: &ldap.Source{
  981. Name: "ldap (simple auth) source full",
  982. Host: "ldap-simple-server full",
  983. Port: 987,
  984. SecurityProtocol: ldap.SecurityProtocol(2),
  985. SkipVerify: true,
  986. UserDN: "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
  987. UserBase: "ou=Users,dc=full-domain-simple,dc=org",
  988. AttributeUsername: "uid-simple full",
  989. AttributeName: "givenName-simple full",
  990. AttributeSurname: "sn-simple full",
  991. AttributeMail: "mail-simple full",
  992. AttributeSSHPublicKey: "publickey-simple full",
  993. Filter: "(&(objectClass=posixAccount)(full-simple-cn=%s))",
  994. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
  995. RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",
  996. },
  997. },
  998. },
  999. },
  1000. // case 1
  1001. {
  1002. args: []string{
  1003. "ldap-test",
  1004. "--id", "1",
  1005. },
  1006. loginSource: &models.LoginSource{
  1007. Type: models.LoginDLDAP,
  1008. Cfg: &models.LDAPConfig{
  1009. Source: &ldap.Source{},
  1010. },
  1011. },
  1012. },
  1013. // case 2
  1014. {
  1015. args: []string{
  1016. "ldap-test",
  1017. "--id", "1",
  1018. "--name", "ldap (simple auth) source",
  1019. },
  1020. loginSource: &models.LoginSource{
  1021. Type: models.LoginDLDAP,
  1022. Name: "ldap (simple auth) source",
  1023. Cfg: &models.LDAPConfig{
  1024. Source: &ldap.Source{
  1025. Name: "ldap (simple auth) source",
  1026. },
  1027. },
  1028. },
  1029. },
  1030. // case 3
  1031. {
  1032. args: []string{
  1033. "ldap-test",
  1034. "--id", "1",
  1035. "--not-active",
  1036. },
  1037. existingLoginSource: &models.LoginSource{
  1038. Type: models.LoginDLDAP,
  1039. IsActived: true,
  1040. Cfg: &models.LDAPConfig{
  1041. Source: &ldap.Source{},
  1042. },
  1043. },
  1044. loginSource: &models.LoginSource{
  1045. Type: models.LoginDLDAP,
  1046. IsActived: false,
  1047. Cfg: &models.LDAPConfig{
  1048. Source: &ldap.Source{},
  1049. },
  1050. },
  1051. },
  1052. // case 4
  1053. {
  1054. args: []string{
  1055. "ldap-test",
  1056. "--id", "1",
  1057. "--security-protocol", "starttls",
  1058. },
  1059. loginSource: &models.LoginSource{
  1060. Type: models.LoginDLDAP,
  1061. Cfg: &models.LDAPConfig{
  1062. Source: &ldap.Source{
  1063. SecurityProtocol: ldap.SecurityProtocol(2),
  1064. },
  1065. },
  1066. },
  1067. },
  1068. // case 5
  1069. {
  1070. args: []string{
  1071. "ldap-test",
  1072. "--id", "1",
  1073. "--skip-tls-verify",
  1074. },
  1075. loginSource: &models.LoginSource{
  1076. Type: models.LoginDLDAP,
  1077. Cfg: &models.LDAPConfig{
  1078. Source: &ldap.Source{
  1079. SkipVerify: true,
  1080. },
  1081. },
  1082. },
  1083. },
  1084. // case 6
  1085. {
  1086. args: []string{
  1087. "ldap-test",
  1088. "--id", "1",
  1089. "--host", "ldap-server",
  1090. },
  1091. loginSource: &models.LoginSource{
  1092. Type: models.LoginDLDAP,
  1093. Cfg: &models.LDAPConfig{
  1094. Source: &ldap.Source{
  1095. Host: "ldap-server",
  1096. },
  1097. },
  1098. },
  1099. },
  1100. // case 7
  1101. {
  1102. args: []string{
  1103. "ldap-test",
  1104. "--id", "1",
  1105. "--port", "987",
  1106. },
  1107. loginSource: &models.LoginSource{
  1108. Type: models.LoginDLDAP,
  1109. Cfg: &models.LDAPConfig{
  1110. Source: &ldap.Source{
  1111. Port: 987,
  1112. },
  1113. },
  1114. },
  1115. },
  1116. // case 8
  1117. {
  1118. args: []string{
  1119. "ldap-test",
  1120. "--id", "1",
  1121. "--user-search-base", "ou=Users,dc=domain,dc=org",
  1122. },
  1123. loginSource: &models.LoginSource{
  1124. Type: models.LoginDLDAP,
  1125. Cfg: &models.LDAPConfig{
  1126. Source: &ldap.Source{
  1127. UserBase: "ou=Users,dc=domain,dc=org",
  1128. },
  1129. },
  1130. },
  1131. },
  1132. // case 9
  1133. {
  1134. args: []string{
  1135. "ldap-test",
  1136. "--id", "1",
  1137. "--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
  1138. },
  1139. loginSource: &models.LoginSource{
  1140. Type: models.LoginDLDAP,
  1141. Cfg: &models.LDAPConfig{
  1142. Source: &ldap.Source{
  1143. Filter: "(&(objectClass=posixAccount)(cn=%s))",
  1144. },
  1145. },
  1146. },
  1147. },
  1148. // case 10
  1149. {
  1150. args: []string{
  1151. "ldap-test",
  1152. "--id", "1",
  1153. "--admin-filter", "(memberOf=cn=admin-group,ou=example,dc=domain,dc=org)",
  1154. },
  1155. loginSource: &models.LoginSource{
  1156. Type: models.LoginDLDAP,
  1157. Cfg: &models.LDAPConfig{
  1158. Source: &ldap.Source{
  1159. AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=domain,dc=org)",
  1160. },
  1161. },
  1162. },
  1163. },
  1164. // case 11
  1165. {
  1166. args: []string{
  1167. "ldap-test",
  1168. "--id", "1",
  1169. "--username-attribute", "uid",
  1170. },
  1171. loginSource: &models.LoginSource{
  1172. Type: models.LoginDLDAP,
  1173. Cfg: &models.LDAPConfig{
  1174. Source: &ldap.Source{
  1175. AttributeUsername: "uid",
  1176. },
  1177. },
  1178. },
  1179. },
  1180. // case 12
  1181. {
  1182. args: []string{
  1183. "ldap-test",
  1184. "--id", "1",
  1185. "--firstname-attribute", "givenName",
  1186. },
  1187. loginSource: &models.LoginSource{
  1188. Type: models.LoginDLDAP,
  1189. Cfg: &models.LDAPConfig{
  1190. Source: &ldap.Source{
  1191. AttributeName: "givenName",
  1192. },
  1193. },
  1194. },
  1195. },
  1196. // case 13
  1197. {
  1198. args: []string{
  1199. "ldap-test",
  1200. "--id", "1",
  1201. "--surname-attribute", "sn",
  1202. },
  1203. loginSource: &models.LoginSource{
  1204. Type: models.LoginDLDAP,
  1205. Cfg: &models.LDAPConfig{
  1206. Source: &ldap.Source{
  1207. AttributeSurname: "sn",
  1208. },
  1209. },
  1210. },
  1211. },
  1212. // case 14
  1213. {
  1214. args: []string{
  1215. "ldap-test",
  1216. "--id", "1",
  1217. "--email-attribute", "mail",
  1218. },
  1219. loginSource: &models.LoginSource{
  1220. Type: models.LoginDLDAP,
  1221. Cfg: &models.LDAPConfig{
  1222. Source: &ldap.Source{
  1223. AttributeMail: "mail",
  1224. },
  1225. },
  1226. },
  1227. },
  1228. // case 15
  1229. {
  1230. args: []string{
  1231. "ldap-test",
  1232. "--id", "1",
  1233. "--public-ssh-key-attribute", "publickey",
  1234. },
  1235. loginSource: &models.LoginSource{
  1236. Type: models.LoginDLDAP,
  1237. Cfg: &models.LDAPConfig{
  1238. Source: &ldap.Source{
  1239. AttributeSSHPublicKey: "publickey",
  1240. },
  1241. },
  1242. },
  1243. },
  1244. // case 16
  1245. {
  1246. args: []string{
  1247. "ldap-test",
  1248. "--id", "1",
  1249. "--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
  1250. },
  1251. loginSource: &models.LoginSource{
  1252. Type: models.LoginDLDAP,
  1253. Cfg: &models.LDAPConfig{
  1254. Source: &ldap.Source{
  1255. UserDN: "cn=%s,ou=Users,dc=domain,dc=org",
  1256. },
  1257. },
  1258. },
  1259. },
  1260. // case 17
  1261. {
  1262. args: []string{
  1263. "ldap-test",
  1264. "--id", "1",
  1265. "--security-protocol", "xxxxx",
  1266. },
  1267. errMsg: "Unknown security protocol name: xxxxx",
  1268. },
  1269. // case 18
  1270. {
  1271. args: []string{
  1272. "ldap-test",
  1273. },
  1274. errMsg: "id is not set",
  1275. },
  1276. // case 19
  1277. {
  1278. args: []string{
  1279. "ldap-test",
  1280. "--id", "1",
  1281. },
  1282. existingLoginSource: &models.LoginSource{
  1283. Type: models.LoginPAM,
  1284. Cfg: &models.LDAPConfig{
  1285. Source: &ldap.Source{},
  1286. },
  1287. },
  1288. errMsg: "Invalid authentication type. expected: LDAP (simple auth), actual: PAM",
  1289. },
  1290. }
  1291. for n, c := range cases {
  1292. // Mock functions.
  1293. var updatedLoginSource *models.LoginSource
  1294. service := &authService{
  1295. initDB: func() error {
  1296. return nil
  1297. },
  1298. createLoginSource: func(loginSource *models.LoginSource) error {
  1299. assert.FailNow(t, "case %d: should not call createLoginSource", n)
  1300. return nil
  1301. },
  1302. updateLoginSource: func(loginSource *models.LoginSource) error {
  1303. updatedLoginSource = loginSource
  1304. return nil
  1305. },
  1306. getLoginSourceByID: func(id int64) (*models.LoginSource, error) {
  1307. if c.id != 0 {
  1308. assert.Equal(t, c.id, id, "case %d: wrong id", n)
  1309. }
  1310. if c.existingLoginSource != nil {
  1311. return c.existingLoginSource, nil
  1312. }
  1313. return &models.LoginSource{
  1314. Type: models.LoginDLDAP,
  1315. Cfg: &models.LDAPConfig{
  1316. Source: &ldap.Source{},
  1317. },
  1318. }, nil
  1319. },
  1320. }
  1321. // Create a copy of command to test
  1322. app := cli.NewApp()
  1323. app.Flags = cmdAuthUpdateLdapSimpleAuth.Flags
  1324. app.Action = service.updateLdapSimpleAuth
  1325. // Run it
  1326. err := app.Run(c.args)
  1327. if c.errMsg != "" {
  1328. assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
  1329. } else {
  1330. assert.NoError(t, err, "case %d: should have no errors", n)
  1331. assert.Equal(t, c.loginSource, updatedLoginSource, "case %d: wrong loginSource", n)
  1332. }
  1333. }
  1334. }