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.

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