more refactor
This commit is contained in:
1 parent
6413447f96
commit
3b78352109
16 files changed
+345
-219
No files matched your search
@@ -11,6 +11,10 @@ import (
|
||||
)
|
||||
|
||||
func Certs(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
var certs_info []map[string]any
|
||||
entires, err := os.ReadDir(os.Getenv("CERTS_PATH"))
|
||||
if err != nil {
|
||||
@@ -43,7 +47,7 @@ func Certs(w http.ResponseWriter, r *http.Request) {
|
||||
new_cert["href"] = fmt.Sprintf("https://%s", entry.Name())
|
||||
new_cert["cert"] = string(certdata)
|
||||
new_cert["key"] = string(keydata)
|
||||
new_cert["certinfo"] = utils.ParseCertificate(fmt.Sprintf("%s/%s/%s.crt", os.Getenv("CERTS_PATH"), entry.Name(), entry.Name()))
|
||||
new_cert["certinfo"] = utils.ParseCert(fmt.Sprintf("%s/%s/%s.crt", os.Getenv("CERTS_PATH"), entry.Name(), entry.Name()))
|
||||
certs_info = append(certs_info, new_cert)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"scm/model"
|
||||
"scm/utils"
|
||||
)
|
||||
|
||||
func CreateCert(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
var requestData model.CreateCertRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
|
||||
http.Error(w, "invalid JSON format", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
caCert, caKey, err := utils.LoadRootCertAndKey(
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.crt",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
"root",
|
||||
"TolaMironcenkoCA",
|
||||
),
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.key",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
"root",
|
||||
"TolaMironcenkoCA",
|
||||
),
|
||||
requestData.CAKeyPassword,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error loading certificate and key:", err)
|
||||
return
|
||||
}
|
||||
// TODO: Implement create certificate endpoint
|
||||
serverKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error generating server key:", err)
|
||||
return
|
||||
}
|
||||
serverCert, err := utils.CreateServerCert(caCert, caKey, serverKey, requestData)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error creating server certificate:", err)
|
||||
return
|
||||
}
|
||||
err = utils.CheckExistsOrCreateDir(requestData.DNSNames[0])
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = utils.SavePEMFile(
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.crt",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
requestData.DNSNames[0],
|
||||
requestData.DNSNames[0],
|
||||
),
|
||||
"CERTIFICATE",
|
||||
serverCert,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error saving certificate:", err)
|
||||
return
|
||||
}
|
||||
err = utils.SavePEMFile(
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.key",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
requestData.DNSNames[0],
|
||||
requestData.DNSNames[0],
|
||||
),
|
||||
"RSA PRIVATE KEY",
|
||||
x509.MarshalPKCS1PrivateKey(serverKey),
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error saving private key:", err)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "%s", `{"status": "success", "message": "Certificate created successfully"}`)
|
||||
}
|
||||
|
||||
// func createServerCert(
|
||||
// caCert *x509.Certificate,
|
||||
// caKey *rsa.PrivateKey,
|
||||
// serverKey *rsa.PrivateKey,
|
||||
// certdata model.CreateCertificateRequest,
|
||||
// ) ([]byte, error) {
|
||||
// // Шаблон серверного сертификата
|
||||
// template := x509.Certificate{
|
||||
// SerialNumber: big.NewInt(time.Now().Unix()),
|
||||
// Subject: pkix.Name{
|
||||
// Organization: certdata.OrganizationName,
|
||||
// CommonName: certdata.CommonName,
|
||||
// OrganizationalUnit: certdata.OrganizationUnit,
|
||||
// },
|
||||
// NotBefore: time.Now(),
|
||||
// NotAfter: time.Now().AddDate(1, 0, 0), // 1 год
|
||||
// KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
// ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
// DNSNames: certdata.DNSNames,
|
||||
// }
|
||||
|
||||
// // Создаем сертификат, подписанный CA
|
||||
// return x509.CreateCertificate(
|
||||
// rand.Reader,
|
||||
// &template,
|
||||
// caCert,
|
||||
// &serverKey.PublicKey,
|
||||
// caKey,
|
||||
// )
|
||||
// }
|
||||
@@ -9,6 +9,10 @@ import (
|
||||
)
|
||||
|
||||
func DeleteCert(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
var requestData model.DeleteCertRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
@@ -13,6 +13,10 @@ var Frontend embed.FS
|
||||
func SpaHandler(fs http.FileSystem) http.Handler {
|
||||
fileServer := http.FileServer(fs)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
fmt.Println("/frontend" + r.URL.Path)
|
||||
r.URL.Path = "/frontend" + path.Clean(r.URL.Path)
|
||||
if _, err := fs.Open(path.Clean(r.URL.Path)); err != nil {
|
||||
@@ -1,181 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"os"
|
||||
"scm/model"
|
||||
"time"
|
||||
|
||||
"github.com/youmark/pkcs8"
|
||||
)
|
||||
|
||||
func CreateCert(w http.ResponseWriter, r *http.Request) {
|
||||
var requestData model.CreateCertificateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
|
||||
http.Error(w, "invalid JSON format", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
caCert, caKey, err := loadCertAndKey(
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.crt",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
"root",
|
||||
"TolaMironcenkoCA",
|
||||
),
|
||||
fmt.Sprintf(
|
||||
"%s/%s/%s.key",
|
||||
os.Getenv("CERTS_PATH"),
|
||||
"root",
|
||||
"TolaMironcenkoCA",
|
||||
),
|
||||
requestData.CAKeyPassword,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error loading certificate and key:", err)
|
||||
return
|
||||
}
|
||||
// TODO: Implement create certificate endpoint
|
||||
serverKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error generating server key:", err)
|
||||
return
|
||||
}
|
||||
serverCert, err := createServerCert(caCert, caKey, serverKey, requestData)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error creating server certificate:", err)
|
||||
return
|
||||
}
|
||||
_, err = os.Stat(fmt.Sprintf("%s/%s", os.Getenv("CERTS_PATH"), requestData.DNSNames[0]))
|
||||
if err == nil {
|
||||
http.Error(w, "certificate already exists", http.StatusConflict)
|
||||
fmt.Println("certificate already exists")
|
||||
return
|
||||
} else if os.IsNotExist(err) {
|
||||
err := os.Mkdir(fmt.Sprintf("%s/%s", os.Getenv("CERTS_PATH"), requestData.DNSNames[0]), 0755)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error creating directory:", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error checking certificate directory:", err)
|
||||
return
|
||||
}
|
||||
err = savePEM(fmt.Sprintf("%s/%s/%s.crt", os.Getenv("CERTS_PATH"), requestData.DNSNames[0], requestData.DNSNames[0]), "CERTIFICATE", serverCert)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error saving certificate:", err)
|
||||
return
|
||||
}
|
||||
err = savePEM(fmt.Sprintf("%s/%s/%s.key", os.Getenv("CERTS_PATH"), requestData.DNSNames[0], requestData.DNSNames[0]), "RSA PRIVATE KEY", x509.MarshalPKCS1PrivateKey(serverKey))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Println("error saving private key:", err)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "%s", `{"status": "success", "message": "Certificate created successfully"}`)
|
||||
}
|
||||
|
||||
func createServerCert(
|
||||
caCert *x509.Certificate,
|
||||
caKey *rsa.PrivateKey,
|
||||
serverKey *rsa.PrivateKey,
|
||||
certdata model.CreateCertificateRequest,
|
||||
) ([]byte, error) {
|
||||
// Шаблон серверного сертификата
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(time.Now().Unix()),
|
||||
Subject: pkix.Name{
|
||||
Organization: certdata.OrganizationName,
|
||||
CommonName: certdata.CommonName,
|
||||
OrganizationalUnit: certdata.OrganizationUnit,
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0), // 1 год
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
DNSNames: certdata.DNSNames,
|
||||
}
|
||||
|
||||
// Создаем сертификат, подписанный CA
|
||||
return x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
&template,
|
||||
caCert,
|
||||
&serverKey.PublicKey,
|
||||
caKey,
|
||||
)
|
||||
}
|
||||
|
||||
func loadCertAndKey(certFile, keyFile, password string) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
fmt.Println(certFile, keyFile)
|
||||
// Загрузка корневого сертификата
|
||||
caCertPEM, err := os.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(caCertPEM)
|
||||
if block == nil {
|
||||
return nil, nil, errors.New("failed to parse CA certificate PEM")
|
||||
}
|
||||
|
||||
caCert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Загрузка зашифрованного приватного ключа
|
||||
keyPEM, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
block, _ = pem.Decode(keyPEM)
|
||||
if block == nil {
|
||||
return nil, nil, errors.New("failed to parse CA key PEM")
|
||||
}
|
||||
fmt.Print(block.Type)
|
||||
// Декодирование ключа с паролем
|
||||
decryptedKey, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, []byte(password))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to decrypt CA key: %v", err)
|
||||
}
|
||||
|
||||
caKey, ok := decryptedKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return caCert, caKey, nil
|
||||
}
|
||||
|
||||
func savePEM(filename, blockType string, data []byte) error {
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = pem.Encode(file, &pem.Block{
|
||||
Type: blockType,
|
||||
Bytes: data,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user