Updated deps, go.19 migration, nginx template work
This commit is contained in:
@ -117,6 +117,21 @@ func getQueryVarInt(r *http.Request, varName string, required bool, defaultValue
|
||||
return varInt, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func getQueryVarBool(r *http.Request, varName string, required bool, defaultValue bool) (bool, error) {
|
||||
queryValues := r.URL.Query()
|
||||
varValue := queryValues.Get(varName)
|
||||
|
||||
if varValue == "" && required {
|
||||
return false, fmt.Errorf("%v was not supplied in the request", varName)
|
||||
} else if varValue == "" {
|
||||
return defaultValue, nil
|
||||
}
|
||||
|
||||
return varValue == "true" || varValue == "1" || varValue == "on", nil
|
||||
}
|
||||
*/
|
||||
|
||||
func getURLParamInt(r *http.Request, varName string) (int, error) {
|
||||
required := true
|
||||
defaultValue := 0
|
||||
|
@ -88,6 +88,8 @@ func UpdateHostTemplate() func(http.ResponseWriter, *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// reconfigure, _ := getQueryVarBool(r, "reconfigure", false, false)
|
||||
|
||||
hostTemplate, err := hosttemplate.GetByID(templateID)
|
||||
if err != nil {
|
||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||
|
@ -2,7 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
c "npm/internal/api/context"
|
||||
@ -15,7 +15,7 @@ func BodyContext() func(http.Handler) http.Handler {
|
||||
// Grab the Body Data
|
||||
var body []byte
|
||||
if r.Body != nil {
|
||||
body, _ = ioutil.ReadAll(r.Body)
|
||||
body, _ = io.ReadAll(r.Body)
|
||||
}
|
||||
// Add it to the context
|
||||
ctx := r.Context()
|
||||
|
@ -38,12 +38,6 @@ var headersAllowedByCORS = []string{
|
||||
"User-Agent",
|
||||
"Cache-Control",
|
||||
"Accept-Encoding",
|
||||
"X-Jumbo-AppKey",
|
||||
"X-Jumbo-SKey",
|
||||
"X-Jumbo-SV",
|
||||
"X-Jumbo-Timestamp",
|
||||
"X-Jumbo-Version",
|
||||
"X-Jumbo-Customer-Id",
|
||||
}
|
||||
|
||||
// Cors handles cors headers
|
||||
|
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"npm/internal/logger"
|
||||
)
|
||||
@ -12,7 +13,14 @@ const httpPort = 3000
|
||||
// StartServer creates a http server
|
||||
func StartServer() {
|
||||
logger.Info("Server starting on port %v", httpPort)
|
||||
err := http.ListenAndServe(fmt.Sprintf(":%v", httpPort), NewRouter())
|
||||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf(":%v", httpPort),
|
||||
Handler: NewRouter(),
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
err := server.ListenAndServe()
|
||||
if err != nil {
|
||||
logger.Error("HttpListenError", err)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"npm/internal/logger"
|
||||
@ -41,9 +40,9 @@ func loadKeys() {
|
||||
|
||||
// Load keys from disk
|
||||
// nolint:gosec
|
||||
publicKeyBytes, publicKeyBytesErr := ioutil.ReadFile(publicKeyFile)
|
||||
publicKeyBytes, publicKeyBytesErr := os.ReadFile(publicKeyFile)
|
||||
// nolint:gosec
|
||||
privateKeyBytes, privateKeyBytesErr := ioutil.ReadFile(privateKeyFile)
|
||||
privateKeyBytes, privateKeyBytesErr := os.ReadFile(privateKeyFile)
|
||||
PublicKey = string(publicKeyBytes)
|
||||
PrivateKey = string(privateKeyBytes)
|
||||
|
||||
@ -96,14 +95,14 @@ func generateKeys() {
|
||||
}
|
||||
|
||||
func saveKeys() {
|
||||
err := ioutil.WriteFile(publicKeyFile, []byte(PublicKey), 0600)
|
||||
err := os.WriteFile(publicKeyFile, []byte(PublicKey), 0600)
|
||||
if err != nil {
|
||||
logger.Error("PublicKeyWriteError", err)
|
||||
} else {
|
||||
logger.Info("Saved Public Key: %s", publicKeyFile)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(privateKeyFile, []byte(PrivateKey), 0600)
|
||||
err = os.WriteFile(privateKeyFile, []byte(PrivateKey), 0600)
|
||||
if err != nil {
|
||||
logger.Error("PrivateKeyWriteError", err)
|
||||
} else {
|
||||
|
@ -264,3 +264,38 @@ func (m *Model) Request() error {
|
||||
logger.Info("Request for certificate for: #%d %v was completed", m.ID, m.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTemplate will convert the Model to a Template
|
||||
func (m *Model) GetTemplate() Template {
|
||||
domainNames, _ := m.DomainNames.AsStringArray()
|
||||
|
||||
t := Template{
|
||||
ID: m.ID,
|
||||
CreatedOn: m.CreatedOn.Time.String(),
|
||||
ModifiedOn: m.ModifiedOn.Time.String(),
|
||||
ExpiresOn: m.ExpiresOn.AsString(),
|
||||
Type: m.Type,
|
||||
UserID: m.UserID,
|
||||
CertificateAuthorityID: m.CertificateAuthorityID,
|
||||
DNSProviderID: m.DNSProviderID,
|
||||
Name: m.Name,
|
||||
DomainNames: domainNames,
|
||||
Status: m.Status,
|
||||
IsECC: m.IsECC,
|
||||
// These are helpers for template generation
|
||||
IsCustom: m.Type == TypeCustom,
|
||||
IsAcme: m.Type != TypeCustom,
|
||||
IsProvided: m.ID > 0 && m.Status == StatusProvided,
|
||||
Folder: m.GetFolder(),
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// GetFolder returns the folder where these certs should exist
|
||||
func (m *Model) GetFolder() string {
|
||||
if m.Type == TypeCustom {
|
||||
return fmt.Sprintf("%s/custom_ssl/npm-%d", config.Configuration.DataFolder, m.ID)
|
||||
}
|
||||
return fmt.Sprintf("%s/npm-%d", config.Configuration.Acmesh.CertHome, m.ID)
|
||||
}
|
||||
|
22
backend/internal/entity/certificate/template.go
Normal file
22
backend/internal/entity/certificate/template.go
Normal file
@ -0,0 +1,22 @@
|
||||
package certificate
|
||||
|
||||
// Template is the model given to the template parser, converted from the Model
|
||||
type Template struct {
|
||||
ID int
|
||||
CreatedOn string
|
||||
ModifiedOn string
|
||||
ExpiresOn string
|
||||
Type string
|
||||
UserID int
|
||||
CertificateAuthorityID int
|
||||
DNSProviderID int
|
||||
Name string
|
||||
DomainNames []string
|
||||
Status string
|
||||
IsECC int
|
||||
// These are helpers for template generation
|
||||
IsCustom bool
|
||||
IsAcme bool // non-custom
|
||||
IsProvided bool
|
||||
Folder string
|
||||
}
|
@ -139,3 +139,37 @@ func (m *Model) Expand(items []string) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTemplate will convert the Model to a Template
|
||||
func (m *Model) GetTemplate() Template {
|
||||
domainNames, _ := m.DomainNames.AsStringArray()
|
||||
|
||||
t := Template{
|
||||
ID: m.ID,
|
||||
CreatedOn: m.CreatedOn.Time.String(),
|
||||
ModifiedOn: m.ModifiedOn.Time.String(),
|
||||
UserID: m.UserID,
|
||||
Type: m.Type,
|
||||
HostTemplateID: m.HostTemplateID,
|
||||
ListenInterface: m.ListenInterface,
|
||||
DomainNames: domainNames,
|
||||
UpstreamID: m.UpstreamID,
|
||||
CertificateID: m.CertificateID,
|
||||
AccessListID: m.AccessListID,
|
||||
SSLForced: m.SSLForced,
|
||||
CachingEnabled: m.CachingEnabled,
|
||||
BlockExploits: m.BlockExploits,
|
||||
AllowWebsocketUpgrade: m.AllowWebsocketUpgrade,
|
||||
HTTP2Support: m.HTTP2Support,
|
||||
HSTSEnabled: m.HSTSEnabled,
|
||||
HSTSSubdomains: m.HSTSSubdomains,
|
||||
Paths: m.Paths,
|
||||
UpstreamOptions: m.UpstreamOptions,
|
||||
AdvancedConfig: m.AdvancedConfig,
|
||||
Status: m.Status,
|
||||
ErrorMessage: m.ErrorMessage,
|
||||
IsDisabled: m.IsDisabled,
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
29
backend/internal/entity/host/template.go
Normal file
29
backend/internal/entity/host/template.go
Normal file
@ -0,0 +1,29 @@
|
||||
package host
|
||||
|
||||
// Template is the model given to the template parser, converted from the Model
|
||||
type Template struct {
|
||||
ID int
|
||||
CreatedOn string
|
||||
ModifiedOn string
|
||||
UserID int
|
||||
Type string
|
||||
HostTemplateID int
|
||||
ListenInterface string
|
||||
DomainNames []string
|
||||
UpstreamID int
|
||||
CertificateID int
|
||||
AccessListID int
|
||||
SSLForced bool
|
||||
CachingEnabled bool
|
||||
BlockExploits bool
|
||||
AllowWebsocketUpgrade bool
|
||||
HTTP2Support bool
|
||||
HSTSEnabled bool
|
||||
HSTSSubdomains bool
|
||||
IsDisabled bool
|
||||
Paths string
|
||||
UpstreamOptions string
|
||||
AdvancedConfig string
|
||||
Status string
|
||||
ErrorMessage string
|
||||
}
|
@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
@ -144,7 +144,7 @@ func TestConfigure(t *testing.T) {
|
||||
func BenchmarkLogLevelBelowThreshold(b *testing.B) {
|
||||
l := NewLogger()
|
||||
|
||||
log.SetOutput(ioutil.Discard)
|
||||
log.SetOutput(io.Discard)
|
||||
defer func() {
|
||||
log.SetOutput(os.Stderr)
|
||||
}()
|
||||
@ -157,7 +157,7 @@ func BenchmarkLogLevelBelowThreshold(b *testing.B) {
|
||||
func BenchmarkLogLevelAboveThreshold(b *testing.B) {
|
||||
l := NewLogger()
|
||||
|
||||
log.SetOutput(ioutil.Discard)
|
||||
log.SetOutput(io.Discard)
|
||||
defer func() {
|
||||
log.SetOutput(os.Stderr)
|
||||
}()
|
||||
|
@ -16,9 +16,8 @@ func ConfigureHost(h host.Model) error {
|
||||
data := TemplateData{
|
||||
ConfDir: fmt.Sprintf("%s/nginx/hosts", config.Configuration.DataFolder),
|
||||
DataDir: config.Configuration.DataFolder,
|
||||
CertsDir: config.Configuration.Acmesh.CertHome,
|
||||
Host: &h,
|
||||
Certificate: h.Certificate,
|
||||
Host: h.GetTemplate(),
|
||||
Certificate: h.Certificate.GetTemplate(),
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("%s/host_%d.conf", data.ConfDir, h.ID)
|
||||
|
@ -15,22 +15,16 @@ func TestWriteTemplate(t *testing.T) {
|
||||
# Host is disabled
|
||||
{{else}}
|
||||
server {
|
||||
{{#if Certificate}}
|
||||
{{#if Certificate.CertificateAuthorityID}}
|
||||
# Acme SSL
|
||||
include {{ConfDir}}/npm/conf.d/acme-challenge.conf;
|
||||
include {{ConfDir}}/npm/conf.d/include/ssl-ciphers.conf;
|
||||
ssl_certificate {{CertsDir}}/npm-{{Certificate.ID}}/fullchain.pem;
|
||||
ssl_certificate_key {{CertsDir}}/npm-{{Certificate.ID}}/privkey.pem;
|
||||
{{else}}
|
||||
# Custom SSL
|
||||
ssl_certificate {{DataDir}}/custom_ssl/npm-{{Certificate.ID}}/fullchain.pem;
|
||||
ssl_certificate_key {{DataDir}}/custom_ssl/npm-{{Certificate.ID}}/privkey.pem;
|
||||
{{#if Certificate.IsProvided}}
|
||||
{{#if Certificate.IsAcme}}
|
||||
include {{ConfDir}}/npm/conf.d/acme-challenge.conf;
|
||||
include {{ConfDir}}/npm/conf.d/include/ssl-ciphers.conf;
|
||||
{{/if}}
|
||||
ssl_certificate {{Certificate.Folder}}/fullchain.pem;
|
||||
ssl_certificate_key {{Certificate.Folder}}/privkey.pem;
|
||||
{{/if}}
|
||||
}
|
||||
{{/if}}
|
||||
|
||||
`
|
||||
|
||||
type want struct {
|
||||
@ -41,36 +35,49 @@ server {
|
||||
tests := []struct {
|
||||
name string
|
||||
data TemplateData
|
||||
host host.Model
|
||||
cert certificate.Model
|
||||
want want
|
||||
}{
|
||||
{
|
||||
name: "Basic Template enabled",
|
||||
data: TemplateData{
|
||||
ConfDir: "/etc/nginx/conf.d",
|
||||
Host: &host.Model{
|
||||
IsDisabled: false,
|
||||
},
|
||||
Certificate: &certificate.Model{
|
||||
CertificateAuthorityID: 0,
|
||||
},
|
||||
host: host.Model{
|
||||
IsDisabled: false,
|
||||
},
|
||||
cert: certificate.Model{
|
||||
ID: 77,
|
||||
Status: certificate.StatusProvided,
|
||||
Type: certificate.TypeHTTP,
|
||||
CertificateAuthorityID: 99,
|
||||
},
|
||||
want: want{
|
||||
output: "\nserver {\n # Custom SSL\n ssl_certificate /custom_ssl/npm-0/fullchain.pem;\n ssl_certificate_key /custom_ssl/npm-0/privkey.pem;\n \n}\n\n",
|
||||
output: "\nserver {\n include /etc/nginx/conf.d/npm/conf.d/acme-challenge.conf;\n include /etc/nginx/conf.d/npm/conf.d/include/ssl-ciphers.conf;\n ssl_certificate /npm-77/fullchain.pem;\n ssl_certificate_key /npm-77/privkey.pem;\n}\n",
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Basic Template custom ssl",
|
||||
host: host.Model{
|
||||
IsDisabled: false,
|
||||
},
|
||||
cert: certificate.Model{
|
||||
ID: 66,
|
||||
Status: certificate.StatusProvided,
|
||||
Type: certificate.TypeCustom,
|
||||
},
|
||||
want: want{
|
||||
output: "\nserver {\n ssl_certificate /custom_ssl/npm-66/fullchain.pem;\n ssl_certificate_key /custom_ssl/npm-66/privkey.pem;\n}\n",
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Basic Template disabled",
|
||||
data: TemplateData{
|
||||
ConfDir: "/etc/nginx/conf.d",
|
||||
DataDir: "/data",
|
||||
CertsDir: "/acme.sh/certs",
|
||||
Host: &host.Model{
|
||||
IsDisabled: true,
|
||||
},
|
||||
host: host.Model{
|
||||
IsDisabled: true,
|
||||
},
|
||||
cert: certificate.Model{},
|
||||
want: want{
|
||||
output: "\n # Host is disabled\n\n",
|
||||
output: "\n # Host is disabled\n",
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
@ -78,7 +85,14 @@ server {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(st *testing.T) {
|
||||
output, err := generateHostConfig(template, test.data)
|
||||
templateData := TemplateData{
|
||||
ConfDir: "/etc/nginx/conf.d",
|
||||
DataDir: "/data",
|
||||
Host: test.host.GetTemplate(),
|
||||
Certificate: test.cert.GetTemplate(),
|
||||
}
|
||||
|
||||
output, err := generateHostConfig(template, templateData)
|
||||
assert.Equal(t, test.want.err, err)
|
||||
assert.Equal(t, test.want.output, output)
|
||||
})
|
||||
|
@ -2,7 +2,7 @@ package nginx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"npm/internal/entity/certificate"
|
||||
"npm/internal/entity/host"
|
||||
@ -11,13 +11,12 @@ import (
|
||||
"github.com/aymerick/raymond"
|
||||
)
|
||||
|
||||
// TemplateData ...
|
||||
// TemplateData is a struct
|
||||
type TemplateData struct {
|
||||
ConfDir string
|
||||
DataDir string
|
||||
CertsDir string
|
||||
Host *host.Model
|
||||
Certificate *certificate.Model
|
||||
Host host.Template
|
||||
Certificate certificate.Template
|
||||
}
|
||||
|
||||
func generateHostConfig(template string, data TemplateData) (string, error) {
|
||||
@ -42,5 +41,5 @@ func writeTemplate(filename, template string, data TemplateData) error {
|
||||
func writeConfigFile(filename, content string) error {
|
||||
logger.Debug("Writing %s with:\n%s", filename, content)
|
||||
// nolint: gosec
|
||||
return ioutil.WriteFile(filename, []byte(content), 0644)
|
||||
return os.WriteFile(filename, []byte(content), 0644)
|
||||
}
|
||||
|
@ -52,3 +52,21 @@ func (d NullableDBDate) MarshalJSON() ([]byte, error) {
|
||||
|
||||
return json.Marshal(d.Time.Unix())
|
||||
}
|
||||
|
||||
// AsInt64 will attempt to return a unixtime
|
||||
func (d NullableDBDate) AsInt64() int64 {
|
||||
if d.Time == nil || d.Time.IsZero() {
|
||||
return 0
|
||||
}
|
||||
|
||||
return d.Time.Unix()
|
||||
}
|
||||
|
||||
// AsString returns date as a string
|
||||
func (d NullableDBDate) AsString() string {
|
||||
if d.Time == nil || d.Time.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return d.Time.String()
|
||||
}
|
||||
|
Reference in New Issue
Block a user