178 lines
4.5 KiB
Go
178 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"strings"
|
|
"golang.org/x/crypto/openpgp"
|
|
"runtime"
|
|
"errors"
|
|
)
|
|
|
|
var VERSION string = "1.1.0"
|
|
|
|
type Conf struct {
|
|
ListenPort string `json:"listenPort"`
|
|
RootRepoPath string `json:"rootRepoPath"`
|
|
SupportArch []string `json:"supportedArch"`
|
|
DistroNames []string `json:"distroNames"`
|
|
PGPSecretKey string `json:"pgpSecretKey"`
|
|
PGPPassphrase string `json:"pgpPassphrase"`
|
|
EnableSSL bool `json:"enableSSL"`
|
|
SSLCert string `json:"SSLcert"`
|
|
SSLKey string `json:"SSLkey"`
|
|
Key string `json:"key"`
|
|
}
|
|
|
|
func (c Conf) DistPath(distro string) string {
|
|
return filepath.Join(c.RootRepoPath, "dists", distro)
|
|
}
|
|
|
|
func (c Conf) ArchPath(distro, arch string) string {
|
|
return filepath.Join(c.RootRepoPath, "dists", distro, "main/binary-"+arch)
|
|
}
|
|
|
|
func (c Conf) PoolPath(distro, arch string) string {
|
|
return filepath.Join(c.RootRepoPath, "pool/main", distro, arch)
|
|
}
|
|
|
|
func (c Conf) PoolPackagePath(distro, arch, name string) string {
|
|
name = packageName(name)
|
|
return filepath.Join(c.RootRepoPath, "pool/main", distro, arch, name[0:1], name)
|
|
}
|
|
|
|
func packageName(name string) string {
|
|
if index := strings.Index(name, "_"); index != -1 {
|
|
name = name[:index]
|
|
}
|
|
return name
|
|
}
|
|
|
|
type DeleteObj struct {
|
|
Filename string
|
|
DistroName string
|
|
Arch string
|
|
}
|
|
|
|
var (
|
|
mutex sync.Mutex
|
|
configFile = flag.String("c", "conf.json", "config file location")
|
|
flagShowVersion = flag.Bool("version", false, "Show dnsconfig version")
|
|
parsedConfig = Conf{}
|
|
pgpEntity *openpgp.Entity
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if *flagShowVersion {
|
|
fmt.Printf("deb-simple %s (%s)\n", VERSION, runtime.Version())
|
|
os.Exit(0)
|
|
}
|
|
|
|
file, err := ioutil.ReadFile(*configFile)
|
|
if err != nil {
|
|
log.Fatalln("unable to read config file, exiting...")
|
|
}
|
|
if err := json.Unmarshal(file, &parsedConfig); err != nil {
|
|
log.Fatalln("unable to marshal config file, exiting...")
|
|
}
|
|
|
|
if err := createDirs(parsedConfig); err != nil {
|
|
log.Println(err)
|
|
log.Fatalln("error creating directory structure, exiting")
|
|
}
|
|
|
|
if err := setupPgp(parsedConfig); err != nil {
|
|
log.Println(err)
|
|
log.Fatalln("error loading pgp key, exiting")
|
|
}
|
|
|
|
http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(parsedConfig.RootRepoPath))))
|
|
http.Handle("/upload", uploadHandler(parsedConfig))
|
|
http.Handle("/delete", deleteHandler(parsedConfig))
|
|
|
|
if parsedConfig.EnableSSL {
|
|
log.Println("running with SSL enabled")
|
|
log.Fatalln(http.ListenAndServeTLS(":"+parsedConfig.ListenPort, parsedConfig.SSLCert, parsedConfig.SSLKey, nil))
|
|
} else {
|
|
log.Println("running without SSL enabled")
|
|
log.Fatalln(http.ListenAndServe(":"+parsedConfig.ListenPort, nil))
|
|
}
|
|
}
|
|
|
|
func setupPgp(config Conf) error {
|
|
if config.PGPSecretKey == "" {
|
|
return nil
|
|
}
|
|
|
|
secretKey, err := os.Open(config.PGPSecretKey)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to open private key ring file: %s", err)
|
|
}
|
|
defer secretKey.Close()
|
|
|
|
entitylist, err := openpgp.ReadKeyRing(secretKey)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read key ring: %s", err)
|
|
}
|
|
|
|
if len(entitylist) < 1 {
|
|
return errors.New("no keys in key ring")
|
|
}
|
|
|
|
pgpEntity = entitylist[0]
|
|
|
|
passphrase := []byte(config.PGPPassphrase)
|
|
|
|
if err := pgpEntity.PrivateKey.Decrypt(passphrase); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, subkey := range pgpEntity.Subkeys {
|
|
err := subkey.PrivateKey.Decrypt(passphrase)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func createDirs(config Conf) error {
|
|
for _, distro := range config.DistroNames {
|
|
for _, arch := range config.SupportArch {
|
|
if _, err := os.Stat(config.ArchPath(distro, arch)); err != nil {
|
|
if os.IsNotExist(err) {
|
|
log.Printf("Directory for %s (%s) does not exist, creating", distro, arch)
|
|
if err := os.MkdirAll(config.ArchPath(distro, arch), 0755); err != nil {
|
|
return fmt.Errorf("error creating directory for %s (%s): %s", distro, arch, err)
|
|
}
|
|
} else {
|
|
return fmt.Errorf("error inspecting %s (%s): %s", distro, arch, err)
|
|
}
|
|
}
|
|
if _, err := os.Stat(config.PoolPath(distro, arch)); err != nil {
|
|
if os.IsNotExist(err) {
|
|
log.Printf("Directory for %s (%s) does not exist, creating", distro, arch)
|
|
if err := os.MkdirAll(config.PoolPath(distro, arch), 0755); err != nil {
|
|
return fmt.Errorf("error creating directory for %s (%s): %s", distro, arch, err)
|
|
}
|
|
} else {
|
|
return fmt.Errorf("error inspecting %s (%s): %s", distro, arch, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|