mirror of
https://github.com/project-zot/zot.git
synced 2025-01-06 22:40:28 -05:00
25f5a45296
As the number of repos and layers increases, the greater the probability that layers are duplicated. We dedupe using hard links when content is the same. This is intended to be purely a storage layer optimization. Access control when available is orthogonal this optimization. Add a durable cache to help speed up layer lookups. Update README. Add more unit tests.
96 lines
2.4 KiB
Go
96 lines
2.4 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/anuvu/zot/errors"
|
|
"github.com/anuvu/zot/pkg/log"
|
|
"github.com/anuvu/zot/pkg/storage"
|
|
"github.com/gorilla/handlers"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
type Controller struct {
|
|
Config *Config
|
|
Router *mux.Router
|
|
ImageStore *storage.ImageStore
|
|
Log log.Logger
|
|
Server *http.Server
|
|
}
|
|
|
|
func NewController(config *Config) *Controller {
|
|
return &Controller{Config: config, Log: log.NewLogger(config.Log.Level, config.Log.Output)}
|
|
}
|
|
|
|
func (c *Controller) Run() error {
|
|
// validate configuration
|
|
if err := c.Config.Validate(c.Log); err != nil {
|
|
c.Log.Error().Err(err).Msg("configuration validation failed")
|
|
return err
|
|
}
|
|
|
|
// print the current configuration, but strip secrets
|
|
c.Log.Info().Interface("params", c.Config.Sanitize()).Msg("configuration settings")
|
|
|
|
engine := mux.NewRouter()
|
|
engine.Use(log.SessionLogger(c.Log), handlers.RecoveryHandler(handlers.RecoveryLogger(c.Log),
|
|
handlers.PrintRecoveryStack(false)))
|
|
|
|
c.ImageStore = storage.NewImageStore(c.Config.Storage.RootDirectory, c.Log)
|
|
if c.ImageStore == nil {
|
|
// we can't proceed without at least a image store
|
|
os.Exit(1)
|
|
}
|
|
|
|
c.Router = engine
|
|
c.Router.UseEncodedPath()
|
|
_ = NewRouteHandler(c)
|
|
|
|
addr := fmt.Sprintf("%s:%s", c.Config.HTTP.Address, c.Config.HTTP.Port)
|
|
server := &http.Server{Addr: addr, Handler: c.Router}
|
|
c.Server = server
|
|
|
|
// Create the listener
|
|
l, err := net.Listen("tcp", addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if c.Config.HTTP.TLS != nil && c.Config.HTTP.TLS.Key != "" && c.Config.HTTP.TLS.Cert != "" {
|
|
if c.Config.HTTP.TLS.CACert != "" {
|
|
clientAuth := tls.VerifyClientCertIfGiven
|
|
if (c.Config.HTTP.Auth == nil || c.Config.HTTP.Auth.HTPasswd.Path == "") && !c.Config.HTTP.AllowReadAccess {
|
|
clientAuth = tls.RequireAndVerifyClientCert
|
|
}
|
|
|
|
caCert, err := ioutil.ReadFile(c.Config.HTTP.TLS.CACert)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
caCertPool := x509.NewCertPool()
|
|
|
|
if !caCertPool.AppendCertsFromPEM(caCert) {
|
|
panic(errors.ErrBadCACert)
|
|
}
|
|
|
|
server.TLSConfig = &tls.Config{
|
|
ClientAuth: clientAuth,
|
|
ClientCAs: caCertPool,
|
|
PreferServerCipherSuites: true,
|
|
MinVersion: tls.VersionTLS12,
|
|
}
|
|
server.TLSConfig.BuildNameToCertificate()
|
|
}
|
|
|
|
return server.ServeTLS(l, c.Config.HTTP.TLS.Cert, c.Config.HTTP.TLS.Key)
|
|
}
|
|
|
|
return server.Serve(l)
|
|
}
|