mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-24 09:18:31 +02:00
feat(api/cert): enhance certificate info retrieval
- Introduced a new method `GetCertInfos` to fetch details of all available certificates. - Updated the `Info` handler to return an array of `CertInfo` instead of a single certificate. - Improved error handling for cases with no available certificates. - Refactored related error messages for clarity.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package certapi
|
package certapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -8,46 +9,33 @@ import (
|
|||||||
apitypes "github.com/yusing/goutils/apitypes"
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CertInfo struct {
|
|
||||||
Subject string `json:"subject"`
|
|
||||||
Issuer string `json:"issuer"`
|
|
||||||
NotBefore int64 `json:"not_before"`
|
|
||||||
NotAfter int64 `json:"not_after"`
|
|
||||||
DNSNames []string `json:"dns_names"`
|
|
||||||
EmailAddresses []string `json:"email_addresses"`
|
|
||||||
} // @name CertInfo
|
|
||||||
|
|
||||||
// @x-id "info"
|
// @x-id "info"
|
||||||
// @BasePath /api/v1
|
// @BasePath /api/v1
|
||||||
// @Summary Get cert info
|
// @Summary Get cert info
|
||||||
// @Description Get cert info
|
// @Description Get cert info
|
||||||
// @Tags cert
|
// @Tags cert
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} CertInfo
|
// @Success 200 {array} autocert.CertInfo
|
||||||
// @Failure 403 {object} apitypes.ErrorResponse
|
// @Failure 403 {object} apitypes.ErrorResponse "Unauthorized"
|
||||||
// @Failure 404 {object} apitypes.ErrorResponse
|
// @Failure 404 {object} apitypes.ErrorResponse "No certificates found or autocert is not enabled"
|
||||||
// @Failure 500 {object} apitypes.ErrorResponse
|
// @Failure 500 {object} apitypes.ErrorResponse "Internal server error"
|
||||||
// @Router /cert/info [get]
|
// @Router /cert/info [get]
|
||||||
func Info(c *gin.Context) {
|
func Info(c *gin.Context) {
|
||||||
autocert := autocert.ActiveProvider.Load()
|
provider := autocert.ActiveProvider.Load()
|
||||||
if autocert == nil {
|
if provider == nil {
|
||||||
c.JSON(http.StatusNotFound, apitypes.Error("autocert is not enabled"))
|
c.JSON(http.StatusNotFound, apitypes.Error("autocert is not enabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cert, err := autocert.GetCert(nil)
|
certInfos, err := provider.GetCertInfos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, autocert.ErrNoCertificates) {
|
||||||
|
c.JSON(http.StatusNotFound, apitypes.Error("no certificate found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
c.Error(apitypes.InternalServerError(err, "failed to get cert info"))
|
c.Error(apitypes.InternalServerError(err, "failed to get cert info"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
certInfo := CertInfo{
|
c.JSON(http.StatusOK, certInfos)
|
||||||
Subject: cert.Leaf.Subject.CommonName,
|
|
||||||
Issuer: cert.Leaf.Issuer.CommonName,
|
|
||||||
NotBefore: cert.Leaf.NotBefore.Unix(),
|
|
||||||
NotAfter: cert.Leaf.NotAfter.Unix(),
|
|
||||||
DNSNames: cert.Leaf.DNSNames,
|
|
||||||
EmailAddresses: cert.Leaf.EmailAddresses,
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, certInfo)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,23 +328,26 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/CertInfo"
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/CertInfo"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"403": {
|
"403": {
|
||||||
"description": "Forbidden",
|
"description": "Unauthorized",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/ErrorResponse"
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "Not Found",
|
"description": "No certificates found or autocert is not enabled",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/ErrorResponse"
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal server error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/ErrorResponse"
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1886,17 +1886,19 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/CertInfo'
|
items:
|
||||||
|
$ref: '#/definitions/CertInfo'
|
||||||
|
type: array
|
||||||
"403":
|
"403":
|
||||||
description: Forbidden
|
description: Unauthorized
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/ErrorResponse'
|
$ref: '#/definitions/ErrorResponse'
|
||||||
"404":
|
"404":
|
||||||
description: Not Found
|
description: No certificates found or autocert is not enabled
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/ErrorResponse'
|
$ref: '#/definitions/ErrorResponse'
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal server error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/ErrorResponse'
|
$ref: '#/definitions/ErrorResponse'
|
||||||
summary: Get cert info
|
summary: Get cert info
|
||||||
|
|||||||
@@ -55,10 +55,20 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
CertExpiries map[string]time.Time
|
CertExpiries map[string]time.Time
|
||||||
RenewMode uint8
|
|
||||||
|
CertInfo struct {
|
||||||
|
Subject string `json:"subject"`
|
||||||
|
Issuer string `json:"issuer"`
|
||||||
|
NotBefore int64 `json:"not_before"`
|
||||||
|
NotAfter int64 `json:"not_after"`
|
||||||
|
DNSNames []string `json:"dns_names"`
|
||||||
|
EmailAddresses []string `json:"email_addresses"`
|
||||||
|
} // @name CertInfo
|
||||||
|
|
||||||
|
RenewMode uint8
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNoCertificate = errors.New("no certificate found")
|
var ErrNoCertificates = errors.New("no certificates found")
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// renew failed for whatever reason, 1 hour cooldown
|
// renew failed for whatever reason, 1 hour cooldown
|
||||||
@@ -98,7 +108,7 @@ func NewProvider(cfg *Config, user *User, legoCfg *lego.Config) (*Provider, erro
|
|||||||
|
|
||||||
func (p *Provider) GetCert(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
func (p *Provider) GetCert(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
if p.tlsCert == nil {
|
if p.tlsCert == nil {
|
||||||
return nil, ErrNoCertificate
|
return nil, ErrNoCertificates
|
||||||
}
|
}
|
||||||
if hello == nil || hello.ServerName == "" {
|
if hello == nil || hello.ServerName == "" {
|
||||||
return p.tlsCert, nil
|
return p.tlsCert, nil
|
||||||
@@ -109,6 +119,29 @@ func (p *Provider) GetCert(hello *tls.ClientHelloInfo) (*tls.Certificate, error)
|
|||||||
return p.tlsCert, nil
|
return p.tlsCert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) GetCertInfos() ([]CertInfo, error) {
|
||||||
|
allProviders := p.allProviders()
|
||||||
|
certInfos := make([]CertInfo, 0, len(allProviders))
|
||||||
|
for _, provider := range allProviders {
|
||||||
|
if provider.tlsCert == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
certInfos = append(certInfos, CertInfo{
|
||||||
|
Subject: provider.tlsCert.Leaf.Subject.CommonName,
|
||||||
|
Issuer: provider.tlsCert.Leaf.Issuer.CommonName,
|
||||||
|
NotBefore: provider.tlsCert.Leaf.NotBefore.Unix(),
|
||||||
|
NotAfter: provider.tlsCert.Leaf.NotAfter.Unix(),
|
||||||
|
DNSNames: provider.tlsCert.Leaf.DNSNames,
|
||||||
|
EmailAddresses: provider.tlsCert.Leaf.EmailAddresses,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(certInfos) == 0 {
|
||||||
|
return nil, ErrNoCertificates
|
||||||
|
}
|
||||||
|
return certInfos, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) GetName() string {
|
func (p *Provider) GetName() string {
|
||||||
if p.cfg.idx == 0 {
|
if p.cfg.idx == 0 {
|
||||||
return "main"
|
return "main"
|
||||||
|
|||||||
Reference in New Issue
Block a user