certs_handlers.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package api
  2. import (
  3. "context"
  4. "encoding/json"
  5. "net/http"
  6. "strings"
  7. "time"
  8. "proxmox-router/internal/certs"
  9. )
  10. func (s *Server) handleListCertificates(w http.ResponseWriter, r *http.Request) {
  11. if s.certMgr == nil {
  12. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  13. return
  14. }
  15. list := s.certMgr.ListCertificates()
  16. writeJSON(w, http.StatusOK, list)
  17. }
  18. func (s *Server) handleGetCertificate(w http.ResponseWriter, r *http.Request) {
  19. if s.certMgr == nil {
  20. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  21. return
  22. }
  23. name := r.PathValue("name")
  24. c, err := s.certMgr.GetCertificate(name)
  25. if err != nil {
  26. writeError(w, http.StatusNotFound, err.Error())
  27. return
  28. }
  29. writeJSON(w, http.StatusOK, c)
  30. }
  31. func (s *Server) handleCreateCA(w http.ResponseWriter, r *http.Request) {
  32. if s.certMgr == nil {
  33. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  34. return
  35. }
  36. var req certs.CreateCARequest
  37. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  38. writeError(w, http.StatusBadRequest, "invalid request payload")
  39. return
  40. }
  41. info, err := s.certMgr.CreateCA(req)
  42. if err != nil {
  43. writeError(w, http.StatusBadRequest, err.Error())
  44. return
  45. }
  46. writeJSON(w, http.StatusCreated, info)
  47. }
  48. func (s *Server) handleCreateCertificate(w http.ResponseWriter, r *http.Request) {
  49. if s.certMgr == nil {
  50. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  51. return
  52. }
  53. var req certs.CreateCertRequest
  54. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  55. writeError(w, http.StatusBadRequest, "invalid request payload")
  56. return
  57. }
  58. info, err := s.certMgr.CreateCertificate(req)
  59. if err != nil {
  60. writeError(w, http.StatusBadRequest, err.Error())
  61. return
  62. }
  63. writeJSON(w, http.StatusCreated, info)
  64. }
  65. func (s *Server) handleImportCertificate(w http.ResponseWriter, r *http.Request) {
  66. if s.certMgr == nil {
  67. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  68. return
  69. }
  70. var req certs.ImportCertRequest
  71. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  72. writeError(w, http.StatusBadRequest, "invalid request payload")
  73. return
  74. }
  75. info, err := s.certMgr.ImportCertificate(req)
  76. if err != nil {
  77. writeError(w, http.StatusBadRequest, err.Error())
  78. return
  79. }
  80. writeJSON(w, http.StatusCreated, info)
  81. }
  82. func (s *Server) handleIssueLetsEncrypt(w http.ResponseWriter, r *http.Request) {
  83. if s.certMgr == nil {
  84. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  85. return
  86. }
  87. var req certs.LetsEncryptRequest
  88. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  89. writeError(w, http.StatusBadRequest, "invalid request payload")
  90. return
  91. }
  92. ctx, cancel := context.WithTimeout(r.Context(), 3*time.Minute)
  93. defer cancel()
  94. info, err := s.certMgr.IssueLetsEncrypt(ctx, req)
  95. if err != nil {
  96. writeError(w, http.StatusBadRequest, err.Error())
  97. return
  98. }
  99. writeJSON(w, http.StatusCreated, info)
  100. }
  101. func (s *Server) handleExportCertificate(w http.ResponseWriter, r *http.Request) {
  102. if s.certMgr == nil {
  103. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  104. return
  105. }
  106. name := r.PathValue("name")
  107. certPEM, keyPEM, err := s.certMgr.ExportPEM(name)
  108. if err != nil {
  109. writeError(w, http.StatusNotFound, err.Error())
  110. return
  111. }
  112. writeJSON(w, http.StatusOK, map[string]string{
  113. "name": name,
  114. "cert_pem": certPEM,
  115. "key_pem": keyPEM,
  116. })
  117. }
  118. func (s *Server) handleDeleteCertificate(w http.ResponseWriter, r *http.Request) {
  119. if s.certMgr == nil {
  120. writeError(w, http.StatusServiceUnavailable, "certificates manager not configured")
  121. return
  122. }
  123. name := r.PathValue("name")
  124. // Prevent deletion if in use by www-ssl
  125. if s.servicesMgr != nil {
  126. if sslSvc, ok := s.servicesMgr.GetService("www-ssl"); ok {
  127. if strings.EqualFold(sslSvc.Certificate, name) && !sslSvc.Disabled {
  128. writeError(w, http.StatusBadRequest, "cannot delete certificate: actively in use by enabled www-ssl service")
  129. return
  130. }
  131. }
  132. }
  133. if err := s.certMgr.DeleteCertificate(name); err != nil {
  134. writeError(w, http.StatusBadRequest, err.Error())
  135. return
  136. }
  137. writeJSON(w, http.StatusOK, map[string]string{"message": "certificate deleted"})
  138. }
  139. func (s *Server) handleACMEChallenge(w http.ResponseWriter, r *http.Request) {
  140. token := r.PathValue("token")
  141. if token == "" {
  142. token = strings.TrimPrefix(r.URL.Path, "/.well-known/acme-challenge/")
  143. }
  144. if s.certMgr == nil {
  145. http.NotFound(w, r)
  146. return
  147. }
  148. keyAuth, ok := s.certMgr.GetHTTP01Challenge(token)
  149. if !ok {
  150. http.NotFound(w, r)
  151. return
  152. }
  153. w.Header().Set("Content-Type", "text/plain")
  154. w.WriteHeader(http.StatusOK)
  155. _, _ = w.Write([]byte(keyAuth))
  156. }