setting_mtls_bundle_test.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package service
  2. import (
  3. "strings"
  4. "testing"
  5. "github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
  6. )
  7. func mustNodeCAPEM(t *testing.T, name string) string {
  8. t.Helper()
  9. ca, err := crypto.GenerateNodeCA(name)
  10. if err != nil {
  11. t.Fatalf("GenerateNodeCA(%q): %v", name, err)
  12. }
  13. return string(ca.CertPEM)
  14. }
  15. func TestParseCertificateBundlePEM(t *testing.T) {
  16. first := mustNodeCAPEM(t, "bundle test CA one")
  17. second := mustNodeCAPEM(t, "bundle test CA two")
  18. corrupt := strings.Replace(second, "-----BEGIN CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nAA", 1)
  19. tests := []struct {
  20. name string
  21. bundle string
  22. wantCerts int
  23. wantErr string
  24. }{
  25. {name: "single certificate", bundle: first, wantCerts: 1},
  26. {name: "two certificates", bundle: first + second, wantCerts: 2},
  27. {name: "empty", bundle: "", wantErr: "certificate bundle is empty"},
  28. {name: "whitespace only", bundle: "\n\t \n", wantErr: "certificate bundle is empty"},
  29. {name: "leading non-PEM data", bundle: "junk\n" + first, wantErr: "certificate bundle contains malformed or non-PEM data"},
  30. {name: "interstitial non-PEM data", bundle: first + "junk\n" + second, wantErr: "certificate bundle contains malformed or non-PEM data"},
  31. {name: "second certificate corrupt", bundle: first + corrupt, wantErr: "certificate bundle contains malformed or non-PEM data"},
  32. {name: "trailing non-PEM data", bundle: first + "not a certificate\n", wantErr: "certificate bundle contains malformed or non-PEM data"},
  33. {name: "non-certificate block", bundle: first + "-----BEGIN PRIVATE KEY-----\nAAAA\n-----END PRIVATE KEY-----\n", wantErr: "certificate bundle contains malformed or non-PEM data"},
  34. }
  35. for _, tt := range tests {
  36. t.Run(tt.name, func(t *testing.T) {
  37. certs, err := parseCertificateBundlePEM([]byte(tt.bundle))
  38. if tt.wantErr != "" {
  39. if err == nil || err.Error() != tt.wantErr {
  40. t.Fatalf("parseCertificateBundlePEM() error = %v, want %q", err, tt.wantErr)
  41. }
  42. return
  43. }
  44. if err != nil {
  45. t.Fatalf("parseCertificateBundlePEM(): %v", err)
  46. }
  47. if len(certs) != tt.wantCerts {
  48. t.Fatalf("parseCertificateBundlePEM() = %d certs, want %d", len(certs), tt.wantCerts)
  49. }
  50. })
  51. }
  52. }
  53. func TestNodeMtlsClientCAPoolRejectsPartiallyValidBundle(t *testing.T) {
  54. s := setupSettingMtlsDB(t)
  55. valid := mustNodeCAPEM(t, "pool test CA")
  56. if err := s.setString("nodeMtlsClientCAPem", valid+"-----BEGIN CERTIFICATE-----\nnot base64\n-----END CERTIFICATE-----\n"); err != nil {
  57. t.Fatalf("setString: %v", err)
  58. }
  59. pool, err := s.NodeMtlsClientCAPool()
  60. want := "nodeMtlsClientCAPem is not a valid certificate bundle: certificate bundle contains malformed or non-PEM data"
  61. if err == nil || err.Error() != want {
  62. t.Fatalf("NodeMtlsClientCAPool() = %v, error = %v, want %q", pool, err, want)
  63. }
  64. }