Get certificate info from local file

This commit is contained in:
0xJacky 2022-08-12 00:23:42 +08:00
parent c747390f94
commit e28e46db32
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
11 changed files with 175 additions and 144 deletions

View file

@ -14,8 +14,8 @@ class Domain extends Curd {
return http.get('template')
}
cert_info(domain: string) {
return http.get('cert/' + domain + '/info')
cert_info(path: string) {
return http.get('cert_info?ssl_certificate_path=' + path)
}
add_auto_cert(domain: string) {

View file

@ -1 +1 @@
{"version":"1.5.0","build_id":40,"total_build":110}
{"version":"1.5.0","build_id":41,"total_build":111}

View file

@ -23,6 +23,11 @@ const name = computed(() => {
return props.directivesMap['server_name'][0].params.trim()
})
const ssl_certificate_path = computed(() => {
return props.directivesMap['ssl_certificate']?.[0].params.trim() ?? null
})
const enabled = computed({
get() {
return props.enabled
@ -36,7 +41,7 @@ const enabled = computed({
<template>
<div>
<cert-info ref="info" :domain="name" v-if="name"/>
<cert-info ref="info" :ssl_certificate_path="ssl_certificate_path" v-if="ssl_certificate_path"/>
<issue-cert
:current_server_directives="props.current_server_directives"
:directives-map="props.directivesMap"

View file

@ -4,7 +4,7 @@ import dayjs from 'dayjs'
import {reactive, ref} from 'vue'
import domain from '@/api/domain'
const props = defineProps(['domain'])
const props = defineProps(['ssl_certificate_path'])
const ok = ref(false)
const cert = reactive({issuer_name: '', subject_name: '', not_after: '', not_before: ''})
@ -12,7 +12,7 @@ const cert = reactive({issuer_name: '', subject_name: '', not_after: '', not_bef
get()
function get() {
domain.cert_info(props.domain).then((r: any) => {
domain.cert_info(props.ssl_certificate_path).then((r: any) => {
Object.assign(cert, r)
ok.value = true
}).catch(() => {

View file

@ -1 +1 @@
{"version":"1.5.0","build_id":40,"total_build":110}
{"version":"1.5.0","build_id":41,"total_build":111}

View file

@ -1,6 +1,7 @@
package api
import (
"github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/server/pkg/cert"
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
"github.com/gin-gonic/gin"
@ -11,14 +12,16 @@ import (
)
func CertInfo(c *gin.Context) {
domain := c.Param("domain")
path := c.Query("ssl_certificate_path")
key, err := cert.GetCertInfo(domain)
log.Println(path)
key, err := cert.GetCertInfo(path)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"message": "Failed to get cert information",
"error": err,
c.JSON(http.StatusInternalServerError, gin.H{
"message": "Failed to get certificate information",
"error": err.Error(),
})
return
}
@ -33,6 +36,7 @@ func CertInfo(c *gin.Context) {
func IssueCert(c *gin.Context) {
domain := c.Param("domain")
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
@ -120,6 +124,22 @@ func IssueCert(c *gin.Context) {
return
}
certModel, err := model.FirstCert(domain)
if err != nil {
log.Println(err)
return
}
err = certModel.Updates(&model.Cert{
SSLCertificatePath: sslCertificatePath,
})
if err != nil {
log.Println(err)
return
}
err = ws.WriteJSON(gin.H{
"status": "success",
"message": "Issued certificate successfully",

View file

@ -248,6 +248,7 @@ func DeleteDomain(c *gin.Context) {
func AddDomainToAutoCert(c *gin.Context) {
domain := c.Param("domain")
cert, err := model.FirstOrCreateCert(domain)
if err != nil {
ErrHandler(c, err)

View file

@ -9,6 +9,7 @@ import (
type Cert struct {
Model
Domain string `json:"domain"`
SSLCertificatePath string `json:"ssl_certificate_path"`
}
func FirstCert(domain string) (c Cert, err error) {
@ -27,8 +28,8 @@ func FirstOrCreateCert(domain string) (c Cert, err error) {
func GetAutoCertList() (c []Cert) {
var t []Cert
db.Find(&t)
// check if this domain is enabled
// check if this domain is enabled
enabledConfig, err := os.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
if err != nil {
@ -49,6 +50,10 @@ func GetAutoCertList() (c []Cert) {
return
}
func (c *Cert) Updates(n *Cert) error {
return db.Model(c).Updates(n).Error
}
func (c *Cert) Remove() error {
return db.Where("domain", c.Domain).Delete(c).Error
}

View file

@ -16,14 +16,28 @@ func AutoCert() {
autoCertList := model.GetAutoCertList()
for i := range autoCertList {
domain := autoCertList[i].Domain
key, err := GetCertInfo(domain)
certModel, err := model.FirstCert(domain)
if err != nil {
log.Println("[AutoCert] Error get certificate from database", err)
continue
}
if certModel.SSLCertificatePath != "" {
log.Println("[AutoCert] Error ssl_certificate_path is empty, " +
"try to reopen auto-cert for this domain:" + domain)
continue
}
cert, err := GetCertInfo(certModel.SSLCertificatePath)
if err != nil {
log.Println("GetCertInfo Err", err)
// Get certificate info error, ignore this domain
continue
}
// before 1 mo
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
if time.Now().Before(cert.NotBefore.AddDate(0, 1, 0)) {
continue
}
// after 1 mo, reissue certificate

View file

@ -1,47 +1,33 @@
package cert
import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"github.com/pkg/errors"
"io"
"log"
"net"
"net/http"
"time"
"os"
)
func GetCertInfo(domain string) (key *x509.Certificate, err error) {
var response *http.Response
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
}).DialContext,
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Timeout: 5 * time.Second,
}
response, err = client.Get("https://" + domain)
func GetCertInfo(sslCertificatePath string) (cert *x509.Certificate, err error) {
certData, err := os.ReadFile(sslCertificatePath)
if err != nil {
err = errors.Wrap(err, "get cert info error")
err = errors.Wrap(err, "error read certificate")
return
}
defer func(Body io.ReadCloser) {
err = Body.Close()
block, _ := pem.Decode(certData)
if block == nil || block.Type != "CERTIFICATE" {
err = errors.New("certificate decoding error")
return
}
cert, err = x509.ParseCertificate(block.Bytes)
if err != nil {
log.Println(err)
err = errors.Wrap(err, "certificate parsing error")
return
}
}(response.Body)
key = response.TLS.PeerCertificates[0]
return
}

View file

@ -84,7 +84,7 @@ func InitRouter() *gin.Engine {
g.GET("template", api.GetTemplate)
g.GET("cert/issue/:domain", api.IssueCert)
g.GET("cert/:domain/info", api.CertInfo)
g.GET("cert_info", api.CertInfo)
// Add domain to auto-renew cert list
g.POST("cert/:domain", api.AddDomainToAutoCert)