transport_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package transport
  2. import (
  3. "encoding/json"
  4. "os"
  5. "testing"
  6. "time"
  7. "github.com/cloudflare/cfssl/api/client"
  8. "github.com/cloudflare/cfssl/csr"
  9. "github.com/cloudflare/cfssl/info"
  10. "github.com/cloudflare/cfssl/log"
  11. "github.com/cloudflare/cfssl/transport/core"
  12. )
  13. var (
  14. testRemote = envOrDefault("CFSSL_REMOTE", "http://127.0.0.1:8888")
  15. testLabel = envOrDefault("CFSSL_LABEL", "")
  16. testProfile = envOrDefault("CFSSL_PROFILE", "transport-test")
  17. disableTests bool
  18. )
  19. func cfsslIsAvailable() bool {
  20. defaultRemote := client.NewServer(testRemote)
  21. infoReq := info.Req{
  22. Profile: testProfile,
  23. Label: testLabel,
  24. }
  25. out, err := json.Marshal(infoReq)
  26. if err != nil {
  27. return false
  28. }
  29. _, err = defaultRemote.Info(out)
  30. if err != nil {
  31. log.Debug("CFSSL remote is unavailable, skipping tests")
  32. return false
  33. }
  34. return true
  35. }
  36. func removeIfPresent(path string) error {
  37. if _, err := os.Stat(path); !os.IsNotExist(err) {
  38. return os.Remove(path)
  39. }
  40. return nil
  41. }
  42. func TestMain(m *testing.M) {
  43. if fi, err := os.Stat("testdata"); os.IsNotExist(err) {
  44. err = os.Mkdir("testdata", 0755)
  45. if err != nil {
  46. log.Fatalf("unable to setup testdata directory: %v", err)
  47. }
  48. } else if fi != nil && !fi.Mode().IsDir() {
  49. log.Fatalf("testdata exists but isn't a directory")
  50. } else if err != nil {
  51. log.Fatalf("%v", err)
  52. }
  53. var exitCode int
  54. if cfsslIsAvailable() {
  55. exitCode = m.Run()
  56. }
  57. err := removeIfPresent(testKey)
  58. if err == nil {
  59. err = removeIfPresent(testCert)
  60. }
  61. if err != nil {
  62. os.Exit(1)
  63. }
  64. err = removeIfPresent(testLKey)
  65. if err == nil {
  66. err = removeIfPresent(testLCert)
  67. }
  68. if err != nil {
  69. os.Exit(1)
  70. }
  71. os.Exit(exitCode)
  72. }
  73. var (
  74. tr *Transport
  75. testKey = "testdata/test.key"
  76. testCert = "testdata/test.pem"
  77. testIdentity = &core.Identity{
  78. Request: &csr.CertificateRequest{
  79. CN: "localhost test certificate",
  80. },
  81. Roots: []*core.Root{
  82. {
  83. Type: "system",
  84. },
  85. {
  86. Type: "cfssl",
  87. Metadata: map[string]string{
  88. "host": testRemote,
  89. "label": testLabel,
  90. "profile": testProfile,
  91. },
  92. },
  93. },
  94. Profiles: map[string]map[string]string{
  95. "paths": {
  96. "private_key": testKey,
  97. "certificate": testCert,
  98. },
  99. "cfssl": {
  100. "label": testLabel,
  101. "profile": testProfile,
  102. "remote": testRemote,
  103. },
  104. },
  105. }
  106. )
  107. func TestTransportSetup(t *testing.T) {
  108. var before = 55 * time.Second
  109. var err error
  110. tr, err = New(before, testIdentity)
  111. if err != nil {
  112. t.Fatalf("failed to set up transport: %v", err)
  113. }
  114. }
  115. func TestRefreshKeys(t *testing.T) {
  116. err := tr.RefreshKeys()
  117. if err != nil {
  118. t.Fatalf("%v", err)
  119. }
  120. }
  121. func TestAutoUpdate(t *testing.T) {
  122. // To force a refresh, make sure that the certificate is
  123. // updated 5 seconds from now.
  124. cert := tr.Provider.Certificate()
  125. if cert == nil {
  126. t.Fatal("no certificate from provider")
  127. }
  128. certUpdates := make(chan time.Time, 0)
  129. errUpdates := make(chan error, 0)
  130. oldBefore := tr.Before
  131. before := cert.NotAfter.Sub(time.Now())
  132. before -= 5 * time.Second
  133. tr.Before = before
  134. defer func() {
  135. tr.Before = oldBefore
  136. PollInterval = 30 * time.Second
  137. }()
  138. PollInterval = 2 * time.Second
  139. go tr.AutoUpdate(certUpdates, errUpdates)
  140. log.Debugf("waiting for certificate update or error from auto updater")
  141. select {
  142. case <-certUpdates:
  143. // Nothing needs to be done
  144. case err := <-errUpdates:
  145. t.Fatalf("%v", err)
  146. case <-time.After(15 * time.Second):
  147. t.Fatal("timeout waiting for update")
  148. }
  149. }
  150. var (
  151. l *Listener
  152. testLKey = "testdata/server.key"
  153. testLCert = "testdata/server.pem"
  154. testLIdentity = &core.Identity{
  155. Request: &csr.CertificateRequest{
  156. CN: "localhost test certificate",
  157. Hosts: []string{"127.0.0.1"},
  158. },
  159. Profiles: map[string]map[string]string{
  160. "paths": {
  161. "private_key": testLKey,
  162. "certificate": testLCert,
  163. },
  164. "cfssl": {
  165. "label": testLabel,
  166. "profile": testProfile,
  167. "remote": testRemote,
  168. },
  169. },
  170. Roots: []*core.Root{
  171. {
  172. Type: "system",
  173. },
  174. {
  175. Type: "cfssl",
  176. Metadata: map[string]string{
  177. "host": testRemote,
  178. "label": testLabel,
  179. "profile": testProfile,
  180. },
  181. },
  182. },
  183. }
  184. )
  185. func testListen(t *testing.T) {
  186. log.Debug("listener waiting for connection")
  187. conn, err := l.Accept()
  188. if err != nil {
  189. panic(err.Error())
  190. }
  191. log.Debugf("client has connected")
  192. conn.Write([]byte("hello"))
  193. conn.Close()
  194. }
  195. func TestListener(t *testing.T) {
  196. var before = 55 * time.Second
  197. trl, err := New(before, testLIdentity)
  198. if err != nil {
  199. t.Fatalf("failed to set up transport: %v", err)
  200. }
  201. trl.Identity.Request.CN = "localhost test server"
  202. err = trl.RefreshKeys()
  203. if err != nil {
  204. t.Fatalf("%v", err)
  205. }
  206. l, err = Listen("127.0.0.1:8765", trl)
  207. if err != nil {
  208. t.Fatalf("%v", err)
  209. }
  210. errChan := make(chan error, 0)
  211. go func() {
  212. err := <-errChan
  213. if err != nil {
  214. panic("listener auto update failed: " + err.Error())
  215. }
  216. }()
  217. cert := trl.Provider.Certificate()
  218. before = cert.NotAfter.Sub(time.Now())
  219. before -= 5 * time.Second
  220. trl.Before = before
  221. go l.AutoUpdate(nil, errChan)
  222. go testListen(t)
  223. <-time.After(1 * time.Second)
  224. log.Debug("dialer making connection")
  225. conn, err := Dial("127.0.0.1:8765", tr)
  226. if err != nil {
  227. log.Debugf("certificate time: %s-%s / %s",
  228. trl.Provider.Certificate().NotBefore,
  229. trl.Provider.Certificate().NotAfter,
  230. time.Now().UTC())
  231. log.Debugf("%#v", trl.Provider.Certificate())
  232. t.Fatalf("%v", err)
  233. }
  234. log.Debugf("client connected to server")
  235. conn.Close()
  236. }