Merge branch 'master' into docker

This commit is contained in:
Brian Martin 2019-06-15 00:12:45 -05:00 committed by GitHub
commit 0b38562b4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 164 additions and 48 deletions

View file

@ -119,13 +119,10 @@ xmppserverlog.addHandler(xmpp_rotate)
logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger
mqtt_listen_address = bumper_listen
mqtt_listen_port = 8883 mqtt_listen_port = 8883
conf1_listen_address = bumper_listen
conf1_listen_port = 443 conf1_listen_port = 443
conf2_listen_address = bumper_listen
conf2_listen_port = 8007 conf2_listen_port = 8007
xmpp_listen_address = bumper_listen
xmpp_listen_port = 5223 xmpp_listen_port = 5223
@ -163,21 +160,19 @@ async def start():
bumperlog.info("Starting Bumper") bumperlog.info("Starting Bumper")
global mqtt_server global mqtt_server
mqtt_server = MQTTServer((mqtt_listen_address, mqtt_listen_port)) mqtt_server = MQTTServer((bumper_listen, mqtt_listen_port))
global mqtt_helperbot global mqtt_helperbot
mqtt_helperbot = MQTTHelperBot((mqtt_listen_address, mqtt_listen_port)) mqtt_helperbot = MQTTHelperBot((bumper_listen, mqtt_listen_port))
global conf_server global conf_server
conf_server = ConfServer( conf_server = ConfServer(
(conf1_listen_address, conf1_listen_port), usessl=True, helperbot=mqtt_helperbot (bumper_listen, conf1_listen_port), usessl=True, helperbot=mqtt_helperbot
) )
global conf_server_2 global conf_server_2
conf_server_2 = ConfServer( conf_server_2 = ConfServer(
(conf2_listen_address, conf2_listen_port), (bumper_listen, conf2_listen_port), usessl=False, helperbot=mqtt_helperbot
usessl=False,
helperbot=mqtt_helperbot,
) )
global xmpp_server global xmpp_server
xmpp_server = XMPPServer((xmpp_listen_address, xmpp_listen_port)) xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port))
# Start web servers # Start web servers
conf_server.confserver_app() conf_server.confserver_app()
@ -1004,14 +999,14 @@ def create_certs():
def first_run(): def first_run():
create_certs() create_certs()
def main(argv=None): def main(argv=None):
import argparse import argparse
global bumper_debug global bumper_debug
global bumper_listen global bumper_listen
global bumper_announce_ip global bumper_announce_ip
if not argv:
argv = sys.argv[1:] # Set argv to argv[1:] if not passed into main
try: try:
if not ( if not (
@ -1033,6 +1028,7 @@ def main(argv=None):
help="announce address to bots on checkin", help="announce address to bots on checkin",
) )
parser.add_argument("--debug", action="store_true", help="enable debug logs") parser.add_argument("--debug", action="store_true", help="enable debug logs")
args = parser.parse_args(args=argv) args = parser.parse_args(args=argv)
if args.debug: if args.debug:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -9,21 +9,82 @@ import (
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"flag"
"fmt"
"log" "log"
"math/big" "math/big"
"net" "net"
"os" "os"
"path/filepath"
"time" "time"
) )
func main() { var InBumperSan string
var OutCertDirectory string
make_CA() func setFlags() {
signCert() exePath, _ := os.Executable()
currentDir, _ := os.Getwd()
//certPath will be current working directory by defaultß
certPath, err := filepath.Abs(currentDir)
if err != nil {
log.Printf("Error: %v", err)
} }
func make_CA() { //sanPath will be exe path /Bumper_SAN.txt by default
sanPath, err := filepath.Abs(filepath.Join(exePath, "..", "/Bumper_SAN.txt"))
if err != nil {
log.Printf("Error: %v", err)
}
flag.StringVar(&InBumperSan, "inSAN", sanPath, "Input file containing a list of Subject Alternate Names (line separated)")
flag.StringVar(&OutCertDirectory, "out", certPath, "Directory to output certificates to")
flag.Parse()
}
func main() {
setFlags()
fmt.Printf("-------- Create_Certs --------\n")
//get absolute path
outCertDirectory, _ := filepath.Abs(OutCertDirectory)
dexists, isdfile := pathExistsType(outCertDirectory)
if !dexists {
log.Fatalf("Certs directory doesn't exist: %v", outCertDirectory)
}
if isdfile {
log.Fatalf("Certs directory is a file, not a directory: %v", outCertDirectory)
}
//get absolute path
inBumperSan, _ := filepath.Abs(InBumperSan)
bexists, isbfile := pathExistsType(inBumperSan)
if !bexists {
log.Printf("Bumper SAN doesn't exist, certificate won't contain Subject Alternate Names: %v\n", inBumperSan)
inBumperSan = ""
}
if bexists && !isbfile {
log.Printf("Bumper SAN is a directory instead of file, certificate won't contain Subject Alternate Names: %v\n", inBumperSan)
inBumperSan = ""
}
fmt.Printf("-------- Starting Certificate Creation --------\n")
fmt.Printf("Options: \n Output Directory: %v\n Input SAN List: %v\n", outCertDirectory, inBumperSan)
make_CA(outCertDirectory)
signCert(outCertDirectory, inBumperSan)
fmt.Printf("-------- Certificate Creation Complete --------\n")
}
func make_CA(outCertDirectory string) {
fmt.Printf("-------- Creating CA Cert --------\n")
priv, _ := rsa.GenerateKey(rand.Reader, 2048) priv, _ := rsa.GenerateKey(rand.Reader, 2048)
pub := &priv.PublicKey pub := &priv.PublicKey
@ -46,40 +107,40 @@ func make_CA() {
ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv) ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv)
if err != nil { if err != nil {
log.Println("create ca failed", err) log.Fatalf("Create ca failed: %v", err)
return
} }
// Public key // Public key
certOut, err := os.Create("ca.crt") certOut, err := os.Create(filepath.Join(outCertDirectory, "ca.crt"))
if err != nil { if err != nil {
log.Fatal("create ca.crt failed", err) log.Fatalf("Create ca.crt failed: %v", err)
} }
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: ca_b}) pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: ca_b})
certOut.Close() certOut.Close()
log.Print("ca.crt created\n") log.Printf("ca.crt created at %v\n", filepath.Join(outCertDirectory, "ca.crt"))
// Private key // Private key
keyOut, err := os.OpenFile("ca.key", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) keyOut, err := os.OpenFile(filepath.Join(outCertDirectory, "ca.key"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
log.Fatal("create ca.key failed", err) log.Fatalf("Create ca.key failed: %v", err)
} }
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close() keyOut.Close()
log.Print("ca.key created\n") log.Printf("ca.key created at %v\n", filepath.Join(outCertDirectory, "ca.key"))
} }
func signCert() { func signCert(outCertDirectory string, inBumperSan string) {
fmt.Printf("-------- Creating Server Cert --------\n")
// Load CA // Load CA
catls, err := tls.LoadX509KeyPair("ca.crt", "ca.key") catls, err := tls.LoadX509KeyPair(filepath.Join(outCertDirectory, "ca.crt"), filepath.Join(outCertDirectory, "ca.key"))
if err != nil { if err != nil {
log.Fatal("error loading ca cert", err) log.Fatalf("Error loading ca cert: %v", err)
} }
ca, err := x509.ParseCertificate(catls.Certificate[0]) ca, err := x509.ParseCertificate(catls.Certificate[0])
if err != nil { if err != nil {
log.Fatal("error parsing ca cert", err) log.Fatalf("Error parsing ca cert: %v", err)
} }
hostname, _ := os.Hostname() hostname, _ := os.Hostname()
@ -109,10 +170,19 @@ func signCert() {
//DNS/SAN names for cert //DNS/SAN names for cert
dnsNames := []string{hostname, "localhost"} dnsNames := []string{hostname, "localhost"}
//Read SANs from file //Read SANs from file
if fileExists("Bumper_SAN.txt") { //get absolute path
sans, err := readLines("Bumper_SAN.txt")
bexists, isbfile := pathExistsType(inBumperSan)
if !bexists {
log.Print("Bumper SAN doesn't exist, certificate won't contain Subject Alternate Names")
}
if bexists && !isbfile {
log.Print("Bumper SAN is a directory instead of file, certificate won't contain Subject Alternate Names")
}
if bexists && isbfile {
sans, err := readLines(inBumperSan)
if err != nil { if err != nil {
log.Fatalf("readLines: %s", err) log.Printf("Error reading %v certificates will be created without Subject Alternate Names: %v", inBumperSan, err)
} }
dnsNames = append(dnsNames, sans...) dnsNames = append(dnsNames, sans...)
} }
@ -141,22 +211,22 @@ func signCert() {
cert_b, err := x509.CreateCertificate(rand.Reader, &template, ca, pubKey, catls.PrivateKey) cert_b, err := x509.CreateCertificate(rand.Reader, &template, ca, pubKey, catls.PrivateKey)
// Public key // Public key
certOut, err := os.Create("bumper.crt") certOut, err := os.Create(filepath.Join(outCertDirectory, "bumper.crt"))
if err != nil { if err != nil {
log.Fatal("create bumper.crt failed", err) log.Fatalf("Create bumper.crt failed: %v", err)
} }
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cert_b}) pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cert_b})
certOut.Close() certOut.Close()
log.Print("bumper.crt created\n") log.Printf("bumper.crt created at %v\n", filepath.Join(outCertDirectory, "bumper.crt"))
// Private key // Private key
keyOut, err := os.OpenFile("bumper.key", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) keyOut, err := os.OpenFile(filepath.Join(outCertDirectory, "bumper.key"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
log.Fatal("create bumper.key failed", err) log.Fatalf("create bumper.key failed: %v", err)
} }
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
keyOut.Close() keyOut.Close()
log.Print("bumper.key created\n") log.Printf("bumper.key created at %v\n", filepath.Join(outCertDirectory, "bumper.key"))
} }
func bigIntHash(n *big.Int) []byte { func bigIntHash(n *big.Int) []byte {
@ -182,12 +252,11 @@ func readLines(path string) ([]string, error) {
return lines, scanner.Err() return lines, scanner.Err()
} }
// fileExists checks if a file exists and is not a directory before we // pathexistsType checks if a path exists and is a file or directory
// try using it to prevent further errors. func pathExistsType(filename string) (exists bool, isfile bool) {
func fileExists(filename string) bool {
info, err := os.Stat(filename) info, err := os.Stat(filename)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return false return false, false
} }
return !info.IsDir() return true, !info.IsDir()
} }

View file

@ -0,0 +1,41 @@
package main
import (
"flag"
"os"
"testing"
)
func TestArgs(t *testing.T) {
orArgs := os.Args
flag.CommandLine = flag.NewFlagSet(orArgs[0], flag.ContinueOnError)
os.Args = []string{"cmd", "-inSAN", "123"}
setFlags()
if InBumperSan != "123" {
t.Error("InBumperSan not set by arg")
}
flag.CommandLine = flag.NewFlagSet(orArgs[0], flag.ContinueOnError)
os.Args = []string{"cmd", "-out", "456"}
setFlags()
if OutCertDirectory != "456" {
t.Error("Out path not set by arg")
}
flag.CommandLine = flag.NewFlagSet(orArgs[0], flag.ContinueOnError)
os.Args = []string{"cmd", "-inSAN", "san1", "-out", "out2"}
setFlags()
if InBumperSan != "san1" {
t.Error("InBumperSan not set by arg")
}
if OutCertDirectory != "out2" {
t.Error("Out path not set by arg")
}
os.Args = orArgs
}

View file

@ -26,7 +26,14 @@ If overriding DNS for the top-level domains isn't an option, you'll need to conf
Not all domains have been documented at this point, and this list will be updated as more are identified/seen. The preferred way to ensure Bumper works is to override the full domains as above. Not all domains have been documented at this point, and this list will be updated as more are identified/seen. The preferred way to ensure Bumper works is to override the full domains as above.
- Example: If you see `eco-{countrycode}-api.ecovacs.com` and you live in the US/North America you would use: `eco-us-api.ecovacs.com` Replacement Examples:
- {countrycode}
- If you see `eco-{countrycode}-api.ecovacs.com` and you live in the US/North America you would use: `eco-us-api.ecovacs.com`
- **Note**: {countrycode} may also be generalized regions such as "EU".
- {region}
- If you see `portal-{region}.ecouser.net` and you live in the US/North America you would use: `portal-na.ecouser.net`
- **Note**: {region} may also be generalized regions such as "EU".
| Address | Description | | Address | Description |
| --------------------------------------- | ---------------------------------------------- | | --------------------------------------- | ---------------------------------------------- |
@ -38,11 +45,14 @@ Not all domains have been documented at this point, and this list will be update
| `gl-{countrycode}-api.ecovacs.com` | Used by EcoVacs Home app | | `gl-{countrycode}-api.ecovacs.com` | Used by EcoVacs Home app |
| `gl-{countrycode}-openapi.ecovacs.com` | Used by EcoVacs Home app | | `gl-{countrycode}-openapi.ecovacs.com` | Used by EcoVacs Home app |
| `portal-{countrycode}.ecouser.net` | Used for Login and Rest API | | `portal-{countrycode}.ecouser.net` | Used for Login and Rest API |
| `portal-{region}.ecouser.net` | Used for Login and Rest API |
| `portal-ww.ecouser.net` | Used for various Rest APIs | | `portal-ww.ecouser.net` | Used for various Rest APIs |
| `msg-{countrycode}.ecouser.net` | Used for XMPP | | `msg-{countrycode}.ecouser.net` | Used for XMPP |
| `msg-{region}.ecouser.net` | Used for XMPP |
| `msg-ww.ecouser.net` | Used for XMPP | | `msg-ww.ecouser.net` | Used for XMPP |
| `mq-ww.ecouser.net` | Used for MQTT |
| `mq-{countrycode}.ecouser.net` | Used for MQTT | | `mq-{countrycode}.ecouser.net` | Used for MQTT |
| `mq-{region}.ecouser.net` | Used for MQTT |
| `mq-ww.ecouser.net` | Used for MQTT |
| `gl-{countrycode}-api.ecovacs.com` | Used by Ecovacs Home app for API | | `gl-{countrycode}-api.ecovacs.com` | Used by Ecovacs Home app for API |
| `recommender.ecovacs.com` | Used by Ecovacs Home app | | `recommender.ecovacs.com` | Used by Ecovacs Home app |
| `bigdata-international.ecovacs.com` | Telemetry/tracking | | `bigdata-international.ecovacs.com` | Telemetry/tracking |

View file

@ -35,8 +35,8 @@ async def test_start_stop():
b = bumper b = bumper
b.db = "tests/tmp.db" # Set db location for testing b.db = "tests/tmp.db" # Set db location for testing
b.conf1_listen_address = "0.0.0.0" b.conf1_listen_address = "127.0.0.1"
b.conf1_listen_port = 443 b.conf1_listen_port = 444
asyncio.create_task(b.start()) asyncio.create_task(b.start())
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
l.check_present(("bumper", "INFO", "Starting Bumper")) l.check_present(("bumper", "INFO", "Starting Bumper"))