Skip to content

refactor: rewrite httpserver package #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions cmd/webhook/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
// - webhookServiceName
// - webhookServiceName.webhookNamespace
// - webhookServiceName.webhookNamespace.svc
func generateTLS() (tls.Certificate, *bytes.Buffer) {
func generateTLS() (keyPair tls.Certificate, caPEM *bytes.Buffer, err error) {
// generate dns names
dnsNames := []string{
webhookServiceName,
Expand All @@ -40,22 +40,24 @@ func generateTLS() (tls.Certificate, *bytes.Buffer) {

caPEM, certPEM, certKeyPEM, err := generateCert([]string{webhookBase}, dnsNames, commonName)
if err != nil {
errorLogger.Fatalf("Failed to generate ca and certificate key pair: %v", err)
errorLogger.Printf("Failed to generate ca and certificate key pair: %v", err)
return
}

pair, err := tls.X509KeyPair(certPEM.Bytes(), certKeyPEM.Bytes())
keyPair, err = tls.X509KeyPair(certPEM.Bytes(), certKeyPEM.Bytes())
if err != nil {
errorLogger.Fatalf("Failed to load certificate key pair: %v", err)
errorLogger.Printf("Failed to load certificate key pair: %v", err)
return
}
return pair, caPEM
return
}

// generateCert generates a self-signed certificate with the given organizations, DNS names, and common name
// The certificate is valid for 1 year
// The certificate is signed by the CA certificate
// The CA certificate is generated with the given organizations
// it resurns the CA, certificate and private key in PEM format.
func generateCert(orgs, dnsNames []string, commonName string) (*bytes.Buffer, *bytes.Buffer, *bytes.Buffer, error) {
func generateCert(orgs, dnsNames []string, commonName string) (caPEM, newCertPEM, newPrivateKeyPEM *bytes.Buffer, err error) {
// init CA config
ca := &x509.Certificate{
SerialNumber: big.NewInt(2022),
Expand All @@ -71,29 +73,35 @@ func generateCert(orgs, dnsNames []string, commonName string) (*bytes.Buffer, *b
// generate private key for CA
caPrivateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
errorLogger.Printf("Failed to generate private key for CA: %v", err)
return nil, nil, nil, err
}

// create the CA certificate
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivateKey.PublicKey, caPrivateKey)
if err != nil {
errorLogger.Printf("Failed to create CA certificate: %v", err)
return nil, nil, nil, err
}

// CA certificate with PEM encoded
caPEM := new(bytes.Buffer)
_ = pem.Encode(caPEM, &pem.Block{
caPEM = new(bytes.Buffer)
err = pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
})
if err != nil {
errorLogger.Printf("Failed to encode CA certificate: %v", err)
return nil, nil, nil, err
}

// print CA certificate if insideCluster is false
if !insideCluster {
writeNewCA(caPEM, manifestWebhookPath)
time.Sleep(2 * time.Second)
applyManifest(manifestWebhookPath)

debugLogger.Printf("CA certificate Encoded: %s", base64.StdEncoding.EncodeToString(caPEM.Bytes()))
// debugLogger.Printf("CA certificate Encoded: %s", base64.StdEncoding.EncodeToString(caPEM.Bytes()))
}

// new certificate config
Expand All @@ -113,28 +121,38 @@ func generateCert(orgs, dnsNames []string, commonName string) (*bytes.Buffer, *b
// generate new private key
newPrivateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
errorLogger.Printf("Failed to generate private key for new certificate: %v", err)
return nil, nil, nil, err
}

// sign the new certificate
newCertBytes, err := x509.CreateCertificate(rand.Reader, newCert, ca, &newPrivateKey.PublicKey, caPrivateKey)
if err != nil {
errorLogger.Printf("Failed to create new certificate: %v", err)
return nil, nil, nil, err
}

// new certificate with PEM encoded
newCertPEM := new(bytes.Buffer)
_ = pem.Encode(newCertPEM, &pem.Block{
newCertPEM = new(bytes.Buffer)
err = pem.Encode(newCertPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: newCertBytes,
})
if err != nil {
errorLogger.Printf("Failed to encode new certificate: %v", err)
return nil, nil, nil, err
}

// new private key with PEM encoded
newPrivateKeyPEM := new(bytes.Buffer)
_ = pem.Encode(newPrivateKeyPEM, &pem.Block{
newPrivateKeyPEM = new(bytes.Buffer)
err = pem.Encode(newPrivateKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(newPrivateKey),
})
if err != nil {
errorLogger.Printf("Failed to encode new private key: %v", err)
return nil, nil, nil, err
}

return caPEM, newCertPEM, newPrivateKeyPEM, nil
}
Expand Down
30 changes: 13 additions & 17 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ func main() {
panic(err)
}

// -- Webhook server -- //
// * Webhook server
// generate cert for webhook
pair, caPEM := generateTLS()
pair, caPEM, err := generateTLS()
if err != nil {
errorLogger.Fatalf("Failed to generate TLS pair: %v", err)
}
tlsC := &tls.Config{
Certificates: []tls.Certificate{pair},
MinVersion: tls.VersionTLS12,
Expand All @@ -103,22 +106,15 @@ func main() {
signalChan <- os.Interrupt
}

// !-- Start the webhook server --! //
waitHTTP := httpserver.Init()
s := httpserver.New(httpserver.WithAddr(webhookPort), httpserver.WithTLSConfig(tlsC))
s.Router.Post(webhookPathMutate, serveHandler)
if err := s.Start(ctx); err != nil {
errorLogger.Fatalf("Failed to start webhook server: %v", err)
}

// !-- Prometheus metrics server --! //
if err = httpserver.StartMetrics(ctx); err != nil {
errorLogger.Fatalf("Failed to start metrics server: %v", err)
// * Config the webhook server
a, waitHTTP := httpserver.Init(ctx)
s, err := a.Add("webhook", httpserver.WithTLS(tlsC), httpserver.WithAddr(webhookPort))
if err != nil {
errorLogger.Fatalf("Failed to create the server: %v", err)
}

// !-- Health check server --! //
if err := httpserver.StartHealth(ctx); err != nil {
errorLogger.Fatalf("Failed to start health check server: %v", err)
s.Config.Post(webhookPathMutate, ServeHandler)
if err := a.Run(); err != nil {
errorLogger.Fatalf("Failed to start HTTP servers: %v", err)
}

// !-- OS signal handling --! //
Expand Down
2 changes: 1 addition & 1 deletion cmd/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

// func serveHandler
func serveHandler(w http.ResponseWriter, r *http.Request) {
func ServeHandler(w http.ResponseWriter, r *http.Request) {
// start the timer
timer := prometheus.NewTimer(promHTTPDuration)
defer timer.ObserveDuration()
Expand Down
13 changes: 1 addition & 12 deletions internal/health/health.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package health

import (
"flag"
"net"
"net/http"
"time"
Expand All @@ -11,21 +10,11 @@ const (
timeoutR = 1 * time.Second
)

var (
healthPath string = "/healthz"
healthPort string = ":9081"
)

func init() {
flag.StringVar(&healthPort, "health-port", healthPort, "Health server port. ex: :9081")
flag.StringVar(&healthPath, "health-path", healthPath, "Health server path. ex: /healthz")
}

// healthHandler returns a http.Handler that returns a health check response
func Handler() http.Handler {
// TODO - Implement a new way to ask the health of the application (e.g. check image updater)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, err := net.DialTimeout("tcp", healthPort, timeoutR)
_, err := net.DialTimeout("tcp", ":9081", timeoutR)
if err != nil {
return
}
Expand Down
Loading
Loading