config_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. package config
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "testing"
  6. "time"
  7. )
  8. var expiry = 1 * time.Minute
  9. var invalidProfileConfig = &Config{
  10. Signing: &Signing{
  11. Profiles: map[string]*SigningProfile{
  12. "invalid": {
  13. Usage: []string{"wiretapping"},
  14. Expiry: expiry,
  15. },
  16. "empty": {},
  17. "invalid-lint": {
  18. Usage: []string{"digital signature"},
  19. Expiry: expiry,
  20. LintErrLevel: 9000,
  21. },
  22. },
  23. Default: &SigningProfile{
  24. Usage: []string{"digital signature"},
  25. Expiry: expiry,
  26. },
  27. },
  28. }
  29. var invalidDefaultConfig = &Config{
  30. Signing: &Signing{
  31. Profiles: map[string]*SigningProfile{
  32. "key usage": {
  33. Usage: []string{"digital signature"},
  34. },
  35. },
  36. Default: &SigningProfile{
  37. Usage: []string{"s/mime"},
  38. },
  39. },
  40. }
  41. var validConfig = &Config{
  42. Signing: &Signing{
  43. Profiles: map[string]*SigningProfile{
  44. "valid": {
  45. Usage: []string{"digital signature"},
  46. Expiry: expiry,
  47. },
  48. "valid-lint": {
  49. Usage: []string{"digital signature"},
  50. Expiry: expiry,
  51. LintErrLevel: 5,
  52. ExcludeLints: []string{"n_subject_common_name_included"},
  53. ExcludeLintSources: []string{"ETSI-ESI"},
  54. },
  55. },
  56. Default: &SigningProfile{
  57. Usage: []string{"digital signature"},
  58. Expiry: expiry,
  59. },
  60. },
  61. }
  62. var validMixedConfig = `
  63. {
  64. "signing": {
  65. "profiles": {
  66. "CA": {
  67. "auth_key": "sample",
  68. "remote": "localhost"
  69. },
  70. "email": {
  71. "usages": ["s/mime"],
  72. "expiry": "720h"
  73. }
  74. },
  75. "default": {
  76. "usages": ["digital signature", "email protection"],
  77. "expiry": "8000h"
  78. }
  79. },
  80. "auth_keys": {
  81. "sample": {
  82. "type":"standard",
  83. "key":"0123456789ABCDEF0123456789ABCDEF"
  84. }
  85. },
  86. "remotes": {
  87. "localhost": "127.0.0.1:8888"
  88. }
  89. }`
  90. var validMinimalRemoteConfig = `
  91. {
  92. "signing": {
  93. "default": {
  94. "auth_key": "sample",
  95. "remote": "localhost"
  96. }
  97. },
  98. "auth_keys": {
  99. "sample": {
  100. "type":"standard",
  101. "key":"0123456789ABCDEF0123456789ABCDEF"
  102. }
  103. },
  104. "remotes": {
  105. "localhost": "127.0.0.1:8888"
  106. }
  107. }`
  108. var validMinimalRemoteConfig2 = `
  109. {
  110. "signing": {
  111. "default": {
  112. "auth_remote":{
  113. "auth_key": "sample",
  114. "remote": "localhost"
  115. }
  116. }
  117. },
  118. "auth_keys": {
  119. "sample": {
  120. "type":"standard",
  121. "key":"0123456789ABCDEF0123456789ABCDEF"
  122. }
  123. },
  124. "remotes": {
  125. "localhost": "127.0.0.1:8888"
  126. }
  127. }`
  128. var invalidConflictRemoteConfig = `
  129. {
  130. "signing": {
  131. "default": {
  132. "auth_remote":{
  133. "auth_key": "sample",
  134. "remote": "localhost"
  135. },
  136. "remote": "localhost"
  137. }
  138. },
  139. "auth_keys": {
  140. "sample": {
  141. "type":"standard",
  142. "key":"0123456789ABCDEF0123456789ABCDEF"
  143. }
  144. },
  145. "remotes": {
  146. "localhost": "127.0.0.1:8888"
  147. }
  148. }`
  149. var invalidRemoteConfig = `
  150. {
  151. "signing": {
  152. "default": {
  153. "auth_remotes_typos":{
  154. "auth_key": "sample",
  155. "remote": "localhost"
  156. }
  157. }
  158. },
  159. "auth_keys": {
  160. "sample": {
  161. "type":"standard",
  162. "key":"0123456789ABCDEF0123456789ABCDEF"
  163. }
  164. },
  165. "remotes": {
  166. "localhost": "127.0.0.1:8888"
  167. }
  168. }`
  169. var invalidAuthRemoteConfigMissingRemote = `
  170. {
  171. "signing": {
  172. "default": {
  173. "auth_remote":{
  174. "auth_key": "sample"
  175. }
  176. }
  177. },
  178. "auth_keys": {
  179. "sample": {
  180. "type":"standard",
  181. "key":"0123456789ABCDEF0123456789ABCDEF"
  182. }
  183. },
  184. "remotes": {
  185. "localhost": "127.0.0.1:8888"
  186. }
  187. }`
  188. var invalidAuthRemoteConfigMissingKey = `
  189. {
  190. "signing": {
  191. "default": {
  192. "auth_remote":{
  193. "remote": "localhost"
  194. }
  195. }
  196. },
  197. "auth_keys": {
  198. "sample": {
  199. "type":"standard",
  200. "key":"0123456789ABCDEF0123456789ABCDEF"
  201. }
  202. },
  203. "remotes": {
  204. "localhost": "127.0.0.1:8888"
  205. }
  206. }`
  207. var validMinimalLocalConfig = `
  208. {
  209. "signing": {
  210. "default": {
  211. "usages": ["digital signature", "email protection"],
  212. "expiry": "8000h"
  213. }
  214. }
  215. }`
  216. var validLocalConfigsWithCAConstraint = []string{
  217. `{
  218. "signing": {
  219. "default": {
  220. "usages": ["digital signature", "email protection"],
  221. "ca_constraint": { "is_ca": true },
  222. "expiry": "8000h"
  223. }
  224. }
  225. }`,
  226. `{
  227. "signing": {
  228. "default": {
  229. "usages": ["digital signature", "email protection"],
  230. "ca_constraint": { "is_ca": true, "max_path_len": 1 },
  231. "expiry": "8000h"
  232. }
  233. }
  234. }`,
  235. `{
  236. "signing": {
  237. "default": {
  238. "usages": ["digital signature", "email protection"],
  239. "ca_constraint": { "is_ca": true, "max_path_len_zero": true },
  240. "expiry": "8000h"
  241. }
  242. }
  243. }`,
  244. }
  245. var copyExtensionWantedlLocalConfig = `
  246. {
  247. "signing": {
  248. "default": {
  249. "expiry": "8000h",
  250. "copy_extensions": true
  251. }
  252. }
  253. }`
  254. var copyExtensionNotWantedlLocalConfig = `
  255. {
  256. "signing": {
  257. "default": {
  258. "expiry": "8000h"
  259. }
  260. }
  261. }`
  262. func TestInvalidProfile(t *testing.T) {
  263. if invalidProfileConfig.Signing.Profiles["invalid"].validProfile(false) {
  264. t.Fatal("invalid profile accepted as valid")
  265. }
  266. if invalidProfileConfig.Signing.Profiles["empty"].validProfile(false) {
  267. t.Fatal("invalid profile accepted as valid")
  268. }
  269. if invalidProfileConfig.Signing.Profiles["invalid-lint"].validProfile(false) {
  270. t.Fatal("invalid profile accepted as valid")
  271. }
  272. if invalidProfileConfig.Valid() {
  273. t.Fatal("invalid config accepted as valid")
  274. }
  275. if !invalidProfileConfig.Signing.Profiles["invalid"].validProfile(true) {
  276. t.Fatal("invalid profile should be a valid default profile")
  277. }
  278. }
  279. func TestRemoteProfiles(t *testing.T) {
  280. var validRemoteProfile = &SigningProfile{
  281. RemoteName: "localhost",
  282. RemoteServer: "localhost:8080",
  283. }
  284. var invalidRemoteProfile = &SigningProfile{
  285. RemoteName: "localhost",
  286. }
  287. var invalidRemoteAuthProfile = &SigningProfile{
  288. RemoteName: "localhost",
  289. RemoteServer: "localhost:8080",
  290. AuthKeyName: "blahblah",
  291. }
  292. if !validRemoteProfile.validProfile(true) ||
  293. !validRemoteProfile.validProfile(false) {
  294. t.Fatal("valid remote profile is rejected.")
  295. }
  296. if invalidRemoteProfile.validProfile(true) ||
  297. invalidRemoteProfile.validProfile(false) {
  298. t.Fatal("invalid remote profile is accepted.")
  299. }
  300. if invalidRemoteAuthProfile.validProfile(true) ||
  301. invalidRemoteAuthProfile.validProfile(false) {
  302. t.Fatal("invalid remote profile is accepted.")
  303. }
  304. }
  305. func TestInvalidDefault(t *testing.T) {
  306. if invalidDefaultConfig.Signing.Default.validProfile(true) {
  307. t.Fatal("invalid default accepted as valid")
  308. }
  309. if invalidDefaultConfig.Valid() {
  310. t.Fatal("invalid config accepted as valid")
  311. }
  312. if !invalidDefaultConfig.Signing.Default.validProfile(false) {
  313. t.Fatal("invalid default profile should be a valid profile")
  314. }
  315. }
  316. func TestValidConfig(t *testing.T) {
  317. if !validConfig.Valid() {
  318. t.Fatal("Valid config is not valid")
  319. }
  320. bytes, _ := json.Marshal(validConfig)
  321. fmt.Printf("%v", string(bytes))
  322. }
  323. func TestDefaultConfig(t *testing.T) {
  324. if !DefaultConfig().validProfile(false) {
  325. t.Fatal("global default signing profile should be a valid profile.")
  326. }
  327. if !DefaultConfig().validProfile(true) {
  328. t.Fatal("global default signing profile should be a valid default profile")
  329. }
  330. }
  331. func TestParse(t *testing.T) {
  332. var validProfiles = []*SigningProfile{
  333. {
  334. ExpiryString: "8760h",
  335. },
  336. {
  337. ExpiryString: "168h",
  338. },
  339. {
  340. ExpiryString: "300s",
  341. },
  342. }
  343. var invalidProfiles = []*SigningProfile{
  344. nil,
  345. {},
  346. {
  347. ExpiryString: "",
  348. },
  349. {
  350. ExpiryString: "365d",
  351. },
  352. {
  353. ExpiryString: "1y",
  354. },
  355. {
  356. ExpiryString: "one year",
  357. },
  358. }
  359. for _, p := range validProfiles {
  360. if p.populate(nil) != nil {
  361. t.Fatalf("Failed to parse ExpiryString=%s", p.ExpiryString)
  362. }
  363. }
  364. for _, p := range invalidProfiles {
  365. if p.populate(nil) == nil {
  366. if p != nil {
  367. t.Fatalf("ExpiryString=%s should not be parsable", p.ExpiryString)
  368. }
  369. t.Fatalf("Nil profile should not be parsable")
  370. }
  371. }
  372. }
  373. func TestPopulateLintRegistry(t *testing.T) {
  374. excludedLintName := "n_subject_common_name_included"
  375. etsiLintName := "w_qcstatem_qctype_web"
  376. profile := &SigningProfile{
  377. ExpiryString: "300s",
  378. ExcludeLints: []string{excludedLintName},
  379. ExcludeLintSources: []string{"ETSI_ESI"},
  380. }
  381. if err := profile.populate(nil); err != nil {
  382. t.Fatal("unexpected error from profile populate")
  383. }
  384. // The LintRegistry shouldn't be nil.
  385. if profile.LintRegistry == nil {
  386. t.Errorf("expected to find non-nil lint registry after populate()")
  387. }
  388. // The excluded lint shouldn't be found in the registry
  389. if l := profile.LintRegistry.ByName(excludedLintName); l != nil {
  390. t.Errorf("expected lint name %q to be filtered out, found %v", excludedLintName, l)
  391. }
  392. // A lint from the excluded source category shouldn't be found in the registry.
  393. if l := profile.LintRegistry.ByName(etsiLintName); l != nil {
  394. t.Errorf("expected lint name %q to be filtered out, found %v", etsiLintName, l)
  395. }
  396. }
  397. func TestLoadFile(t *testing.T) {
  398. validConfigFiles := []string{
  399. "testdata/valid_config.json",
  400. "testdata/valid_config_auth.json",
  401. "testdata/valid_config_no_default.json",
  402. "testdata/valid_config_auth_no_default.json",
  403. }
  404. for _, configFile := range validConfigFiles {
  405. _, err := LoadFile(configFile)
  406. if err != nil {
  407. t.Fatal("Load valid config file failed.", configFile, "error is ", err)
  408. }
  409. }
  410. }
  411. func TestLoadInvalidConfigFile(t *testing.T) {
  412. invalidConfigFiles := []string{"", "testdata/no_such_file",
  413. "testdata/invalid_default.json",
  414. "testdata/invalid_profiles.json",
  415. "testdata/invalid_usage.json",
  416. "testdata/invalid_config.json",
  417. "testdata/invalid_auth.json",
  418. "testdata/invalid_auth_bad_key.json",
  419. "testdata/invalid_no_auth_keys.json",
  420. "testdata/invalid_remote.json",
  421. "testdata/invalid_no_remotes.json",
  422. }
  423. for _, configFile := range invalidConfigFiles {
  424. _, err := LoadFile(configFile)
  425. if err == nil {
  426. t.Fatal("Invalid config is loaded.", configFile)
  427. }
  428. }
  429. }
  430. func TestNeedLocalSigner(t *testing.T) {
  431. c, err := LoadConfig([]byte(validMixedConfig))
  432. if err != nil {
  433. t.Fatal("load valid config failed:", err)
  434. }
  435. // This signing config needs both local signer and remote signer.
  436. if c.Signing.NeedsLocalSigner() != true {
  437. t.Fatal("incorrect NeedsLocalSigner().")
  438. }
  439. if c.Signing.NeedsRemoteSigner() != true {
  440. t.Fatal("incorrect NeedsRemoteSigner()")
  441. }
  442. remoteConfig, err := LoadConfig([]byte(validMinimalRemoteConfig))
  443. if err != nil {
  444. t.Fatal("Load valid config failed:", err)
  445. }
  446. if remoteConfig.Signing.NeedsLocalSigner() != false {
  447. t.Fatal("incorrect NeedsLocalSigner().")
  448. }
  449. if remoteConfig.Signing.NeedsRemoteSigner() != true {
  450. t.Fatal("incorrect NeedsRemoteSigner().")
  451. }
  452. localConfig, err := LoadConfig([]byte(validMinimalLocalConfig))
  453. if localConfig.Signing.NeedsLocalSigner() != true {
  454. t.Fatal("incorrect NeedsLocalSigner().")
  455. }
  456. if localConfig.Signing.NeedsRemoteSigner() != false {
  457. t.Fatal("incorrect NeedsRemoteSigner().")
  458. }
  459. if err != nil {
  460. t.Fatal(err)
  461. }
  462. }
  463. func TestOverrideRemotes(t *testing.T) {
  464. c, err := LoadConfig([]byte(validMixedConfig))
  465. if err != nil {
  466. t.Fatal("load valid config failed:", err)
  467. }
  468. host := "localhost:8888"
  469. c.Signing.OverrideRemotes(host)
  470. if c.Signing.Default.RemoteServer != host {
  471. t.Fatal("should override default profile's RemoteServer")
  472. }
  473. for _, p := range c.Signing.Profiles {
  474. if p.RemoteServer != host {
  475. t.Fatal("failed to override profile's RemoteServer")
  476. }
  477. }
  478. }
  479. func TestAuthRemoteConfig(t *testing.T) {
  480. c, err := LoadConfig([]byte(validMinimalRemoteConfig2))
  481. if err != nil {
  482. t.Fatal("load valid config failed:", err)
  483. }
  484. if c.Signing.Default.RemoteServer != "127.0.0.1:8888" {
  485. t.Fatal("load valid config failed: incorrect remote server")
  486. }
  487. host := "localhost:8888"
  488. c.Signing.OverrideRemotes(host)
  489. if c.Signing.Default.RemoteServer != host {
  490. t.Fatal("should override default profile's RemoteServer")
  491. }
  492. for _, p := range c.Signing.Profiles {
  493. if p.RemoteServer != host {
  494. t.Fatal("failed to override profile's RemoteServer")
  495. }
  496. }
  497. }
  498. func TestDuplicateRemoteConfig(t *testing.T) {
  499. _, err := LoadConfig([]byte(invalidConflictRemoteConfig))
  500. if err == nil {
  501. t.Fatal("fail to reject invalid config")
  502. }
  503. }
  504. func TestBadAuthRemoteConfig(t *testing.T) {
  505. _, err := LoadConfig([]byte(invalidRemoteConfig))
  506. if err == nil {
  507. t.Fatal("load invalid config should failed")
  508. }
  509. _, err = LoadConfig([]byte(invalidAuthRemoteConfigMissingRemote))
  510. if err == nil {
  511. t.Fatal("load invalid config should failed")
  512. }
  513. _, err = LoadConfig([]byte(invalidAuthRemoteConfigMissingKey))
  514. if err == nil {
  515. t.Fatal("load invalid config should failed")
  516. }
  517. var p *Signing
  518. if p.Valid() {
  519. t.Fatal("nil Signing config should be invalid")
  520. }
  521. }
  522. func TestValidCAConstraint(t *testing.T) {
  523. for _, config := range validLocalConfigsWithCAConstraint {
  524. _, err := LoadConfig([]byte(config))
  525. if err != nil {
  526. t.Fatal("can't parse valid ca constraint")
  527. }
  528. }
  529. }
  530. func TestWantCopyExtension(t *testing.T) {
  531. localConfig, err := LoadConfig([]byte(copyExtensionWantedlLocalConfig))
  532. if localConfig.Signing.Default.CopyExtensions != true {
  533. t.Fatal("incorrect TestWantCopyExtension().")
  534. }
  535. if err != nil {
  536. t.Fatal(err)
  537. }
  538. }
  539. func TestDontWantCopyExtension(t *testing.T) {
  540. localConfig, err := LoadConfig([]byte(copyExtensionNotWantedlLocalConfig))
  541. if localConfig.Signing.Default.CopyExtensions != false {
  542. t.Fatal("incorrect TestDontWantCopyExtension().")
  543. }
  544. if err != nil {
  545. t.Fatal(err)
  546. }
  547. }