diff --git a/api/CertDownload.go b/api/CertDownload.go
new file mode 100644
index 0000000..0aecfc3
--- /dev/null
+++ b/api/CertDownload.go
@@ -0,0 +1,47 @@
+package api
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "path/filepath"
+ "scm/utils"
+)
+
+func CertKeyDownloadZip(w http.ResponseWriter, r *http.Request) {
+ query := r.URL.Query()
+ domain := query.Get("domain")
+ if domain == "" {
+ http.Error(w, "domain parameter is required", http.StatusBadRequest)
+ return
+ }
+
+ // Пути к файлам сертификата и ключа
+ certPath := filepath.Join(os.Getenv("CERTS_PATH"), domain, domain+".crt")
+ keyPath := filepath.Join(os.Getenv("CERTS_PATH"), domain, domain+".key")
+
+ // Проверяем существование файлов
+ if _, err := os.Stat(certPath); os.IsNotExist(err) {
+ http.Error(w, "Certificate file not found", http.StatusNotFound)
+ return
+ }
+ if _, err := os.Stat(keyPath); os.IsNotExist(err) {
+ http.Error(w, "Key file not found", http.StatusNotFound)
+ return
+ }
+
+ // Создаем ZIP архив
+ zipBuffer, err := utils.CreateDomainZip(certPath, keyPath, domain)
+ if err != nil {
+ http.Error(w, fmt.Sprintf("Error creating zip: %v", err), http.StatusInternalServerError)
+ return
+ }
+
+ // Устанавливаем заголовки для скачивания
+ w.Header().Set("Content-Type", "application/zip")
+ w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s-cert-key.zip\"", domain))
+ w.Header().Set("Content-Length", fmt.Sprintf("%d", zipBuffer.Len()))
+
+ // Отправляем ZIP архив
+ w.Write(zipBuffer.Bytes())
+}
diff --git a/api/frontend/index.html b/api/frontend/index.html
index 15f0af2..c6fe309 100644
--- a/api/frontend/index.html
+++ b/api/frontend/index.html
@@ -62,13 +62,15 @@
-
+
@@ -91,71 +93,78 @@
>
-
@@ -315,114 +324,124 @@
-
diff --git a/api/frontend/js/certs.js b/api/frontend/js/certs.js
index 9577de4..8fdaa8e 100644
--- a/api/frontend/js/certs.js
+++ b/api/frontend/js/certs.js
@@ -34,9 +34,9 @@ const renderCards = () => {
>
Cert
-
+
diff --git a/api/frontend/js/create_cert.js b/api/frontend/js/create_cert.js
index 0fa45a8..434d486 100644
--- a/api/frontend/js/create_cert.js
+++ b/api/frontend/js/create_cert.js
@@ -3,42 +3,45 @@ const commonname = document.querySelector("#commonname");
const organizationname = document.querySelector("#organizationname");
const password = document.querySelector("#password");
const organizationunit = document.querySelector("#organizationunit");
-const createcert = document.querySelector("#createcert");
+const create_certificate_form = document.querySelector(
+ "#create_certificate_form",
+);
-createcert.addEventListener("click", () => {
- const domainValue = domain.value;
- const commonnameValue = commonname.value;
- const organizationnameValue = organizationname.value;
- const passwordValue = password.value;
- const organizationunitValue = organizationunit.value;
+create_certificate_form.addEventListener("submit", (event) => {
+ event.preventDefault();
+ const domainValue = domain.value;
+ const commonnameValue = commonname.value;
+ const organizationnameValue = organizationname.value;
+ const passwordValue = password.value;
+ const organizationunitValue = organizationunit.value;
- fetch(window.location.origin + "/api/certs/create", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- dns: [domainValue],
- commonname: commonnameValue,
- organizationname: [organizationnameValue],
- organizationunit: [organizationunitValue],
- password: passwordValue,
- }),
+ fetch(window.location.origin + "/api/certs/create", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ dns: [domainValue],
+ commonname: commonnameValue,
+ organizationname: [organizationnameValue],
+ organizationunit: [organizationunitValue],
+ password: passwordValue,
+ }),
+ })
+ .then((data) => data.json())
+ .then((jsondata) => {
+ if (jsondata.status === "success") {
+ getCerts();
+ var createmodal = bootstrap.Modal.getOrCreateInstance(
+ document.getElementById("create_certificate"),
+ );
+ createmodal.hide();
+ alert("Certificate created successfully");
+ } else {
+ alert("Failed to create certificate:", jsondata.error);
+ }
})
- .then((data) => data.json())
- .then((jsondata) => {
- if (jsondata.status === "success") {
- getCerts();
- var createmodal = bootstrap.Modal.getOrCreateInstance(
- document.getElementById("create_certificate"),
- );
- createmodal.hide();
- alert("Certificate created successfully");
- } else {
- alert("Failed to create certificate:", jsondata.error);
- }
- })
- .catch((error) => {
- alert("An error occurred:", error);
- });
+ .catch((error) => {
+ alert("An error occurred:", error);
+ });
});
diff --git a/api/frontend/js/rootcrt.js b/api/frontend/js/rootcrt.js
index 3253782..6991cb4 100644
--- a/api/frontend/js/rootcrt.js
+++ b/api/frontend/js/rootcrt.js
@@ -1,7 +1,9 @@
const createRootCertificateModal = bootstrap.Modal.getOrCreateInstance(
document.querySelector("#createRootCertificate"),
);
-const createRootCrtButton = document.querySelector("#createRootCrt");
+const createRootCertificateForm = document.querySelector(
+ "#createRootCertificateForm",
+);
const rootcommonnameinput = document.querySelector("#rootcommonname");
const rootorganizationinput = document.querySelector("#rootorganizationname");
@@ -29,7 +31,8 @@ const getRootCrt = () => {
getRootCrt();
-createRootCrtButton.addEventListener("click", () => {
+createRootCertificateForm.addEventListener("submit", (event) => {
+ event.preventDefault();
const newRootCertificate = {
CommonName: rootcommonnameinput.value,
Organization: [rootorganizationinput.value],
diff --git a/server/Configure.go b/server/Configure.go
index 9f52926..59637b3 100644
--- a/server/Configure.go
+++ b/server/Configure.go
@@ -9,6 +9,7 @@ func Configure() {
http.Handle("/", api.SpaHandler(http.FS(api.Frontend)))
http.HandleFunc("/api/certs", api.Certs)
http.HandleFunc("/api/certs/root", api.RootCert)
+ http.HandleFunc("/api/certs/download/", api.CertKeyDownloadZip)
http.HandleFunc("/api/certs/create", api.CreateCert)
http.HandleFunc("/api/certs/delete", api.DeleteCert)
}
diff --git a/utils/AddFileToZipWithName.go b/utils/AddFileToZipWithName.go
new file mode 100644
index 0000000..06ee214
--- /dev/null
+++ b/utils/AddFileToZipWithName.go
@@ -0,0 +1,21 @@
+package utils
+
+import (
+ "archive/zip"
+ "os"
+)
+
+func AddFileToZipWithName(zipWriter *zip.Writer, filePath, fileName string) error {
+ data, err := os.ReadFile(filePath)
+ if err != nil {
+ return err
+ }
+
+ f, err := zipWriter.Create(fileName)
+ if err != nil {
+ return err
+ }
+
+ _, err = f.Write(data)
+ return err
+}
diff --git a/utils/CreateDomainZip.go b/utils/CreateDomainZip.go
new file mode 100644
index 0000000..7415e83
--- /dev/null
+++ b/utils/CreateDomainZip.go
@@ -0,0 +1,26 @@
+package utils
+
+import (
+ "archive/zip"
+ "bytes"
+)
+
+func CreateDomainZip(certPath, keyPath, domain string) (*bytes.Buffer, error) {
+ buf := new(bytes.Buffer)
+ zipWriter := zip.NewWriter(buf)
+ defer zipWriter.Close()
+
+ // Добавляем сертификат
+ err := AddFileToZipWithName(zipWriter, certPath, domain+".crt")
+ if err != nil {
+ return nil, err
+ }
+
+ // Добавляем ключ
+ err = AddFileToZipWithName(zipWriter, keyPath, domain+".key")
+ if err != nil {
+ return nil, err
+ }
+
+ return buf, nil
+}