delete create_certs functionality

This commit is contained in:
Robert Resch 2021-06-17 22:11:47 +02:00
parent 3a7ce8c6e2
commit bbb2700a75
No known key found for this signature in database
GPG key ID: 6B360759EB2ACAEE
12 changed files with 6 additions and 480 deletions

View file

@ -30,7 +30,6 @@ RUN pip3 install -r requirements.txt
WORKDIR /bumper WORKDIR /bumper
# Copy only required folders instead of all # Copy only required folders instead of all
COPY create_certs/ create_certs/
COPY bumper/ bumper/ COPY bumper/ bumper/
ENTRYPOINT ["python3", "-m", "bumper"] ENTRYPOINT ["python3", "-m", "bumper"]

View file

@ -189,54 +189,6 @@ async def shutdown():
bumperlog.info("Shutdown complete") bumperlog.info("Shutdown complete")
def create_certs():
import platform
import os
import subprocess
import sys
path = os.path.dirname(sys.modules[__name__].__file__)
path = os.path.join(path, "..")
sys.path.insert(0, path)
print("Creating certificates")
odir = os.path.realpath(os.curdir)
os.chdir("certs")
if str(platform.system()).lower() == "windows":
# run for win
subprocess.run([os.path.join("..", "create_certs", "create_certs_windows.exe")])
elif str(platform.system()).lower() == "darwin":
# run on mac
subprocess.run([os.path.join("..", "create_certs", "create_certs_osx")])
elif str(platform.system()).lower() == "linux":
if "arm" in platform.machine().lower() or "aarch64" in platform.machine().lower():
# run for pi
subprocess.run([os.path.join("..", "create_certs", "create_certs_rpi")])
else:
# run for linux
subprocess.run([os.path.join("..", "create_certs", "create_certs_linux")])
else:
os.chdir(odir)
bumperlog.fatal("Can't determine platform. Create certs manually and try again.")
return
print("Certificates created")
os.chdir(odir)
if "__main__.py" in sys.argv[0]:
os.execv(
sys.executable, ["python", "-m", "bumper"] + sys.argv[1:]
) # Start again
else:
os.execv(sys.executable, ["python"] + sys.argv) # Start again
def first_run():
create_certs()
def main(argv=None): def main(argv=None):
import argparse import argparse
@ -252,8 +204,9 @@ def main(argv=None):
and os.path.exists(server_cert) and os.path.exists(server_cert)
and os.path.exists(server_key) and os.path.exists(server_key)
): ):
first_run() msg = "No certs found! Please generate them (More infos in the docs)"
return bumperlog.fatal(msg)
sys.exit(msg)
if not ( if not (
os.path.exists(os.path.join(data_dir, "passwd")) os.path.exists(os.path.join(data_dir, "passwd"))

View file

@ -1,10 +0,0 @@
ecovacs.com
*.ecovacs.com
ecouser.net
*.ecouser.net
ecovacs.net
*.ecovacs.net
*.ww.ecouser.net
*.dc-eu.ww.ecouser.net
*.dc.ww.ecouser.net
*.area.ww.ecouser.net

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,12 +0,0 @@
#!/bin/bash
SCRIPTPATH=$(dirname "$BASH_SOURCE")
OUTPUTPATH=$(dirname $(dirname "$BASH_SOURCE"))
echo "Building for Windows: $OUTPUTPATH/create_certs_windows.exe"
GOOS=windows go build -o $OUTPUTPATH/create_certs_windows.exe $SCRIPTPATH/create_certs.go
echo "Building for OSX $OUTPUTPATH/create_certs_osx"
GOOS=darwin go build -o $OUTPUTPATH/create_certs_osx $SCRIPTPATH/create_certs.go
echo "Building for Linux $OUTPUTPATH/create_certs_linux"
GOOS=linux go build -o $OUTPUTPATH/create_certs_linux $SCRIPTPATH/create_certs.go
echo "Building for ARM (Raspberry Pi) $OUTPUTPATH/create_certs_rpi"
GOOS=linux GOARCH=arm GOARM=5 go build -o $OUTPUTPATH/create_certs_rpi $SCRIPTPATH/create_certs.go
echo "Build Complete"

View file

@ -1,262 +0,0 @@
package main
import (
"bufio"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"net"
"os"
"path/filepath"
"time"
)
var InBumperSan string
var OutCertDirectory string
func setFlags() {
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)
}
//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)
pub := &priv.PublicKey
ca := &x509.Certificate{
SerialNumber: big.NewInt(1653),
Subject: pkix.Name{
CommonName: string("Bumper CA"),
Organization: []string{"Bumper"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(2, 0, 0),
SubjectKeyId: bigIntHash(priv.N),
AuthorityKeyId: bigIntHash(priv.N),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{},
IsCA: true,
BasicConstraintsValid: true,
MaxPathLen: -1,
}
ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv)
if err != nil {
log.Fatalf("Create ca failed: %v", err)
}
// Public key
certOut, err := os.Create(filepath.Join(outCertDirectory, "ca.crt"))
if err != nil {
log.Fatalf("Create ca.crt failed: %v", err)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: ca_b})
certOut.Close()
log.Printf("ca.crt created at %v\n", filepath.Join(outCertDirectory, "ca.crt"))
// Private key
keyOut, err := os.OpenFile(filepath.Join(outCertDirectory, "ca.key"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("Create ca.key failed: %v", err)
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
log.Printf("ca.key created at %v\n", filepath.Join(outCertDirectory, "ca.key"))
}
func signCert(outCertDirectory string, inBumperSan string) {
fmt.Printf("-------- Creating Server Cert --------\n")
// Load CA
catls, err := tls.LoadX509KeyPair(filepath.Join(outCertDirectory, "ca.crt"), filepath.Join(outCertDirectory, "ca.key"))
if err != nil {
log.Fatalf("Error loading ca cert: %v", err)
}
ca, err := x509.ParseCertificate(catls.Certificate[0])
if err != nil {
log.Fatalf("Error parsing ca cert: %v", err)
}
hostname, _ := os.Hostname()
ifaces, err := net.Interfaces()
var ips []net.IP
// handle err
for _, i := range ifaces {
addrs, _ := i.Addrs()
// handle err
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
ips = append(ips, ip)
// process IP address
}
}
ips = append(ips, net.ParseIP("127.0.0.1"))
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
pubKey := &privateKey.PublicKey
//DNS/SAN names for cert
dnsNames := []string{hostname, "localhost"}
//Read SANs from file
//get absolute path
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 {
log.Printf("Error reading %v certificates will be created without Subject Alternate Names: %v", inBumperSan, err)
}
dnsNames = append(dnsNames, sans...)
}
// Prepare certificate
template := x509.Certificate{
SerialNumber: big.NewInt(1658),
Issuer: ca.Subject,
Subject: pkix.Name{
CommonName: "Bumper Server",
Organization: []string{"Bumper"},
},
SubjectKeyId: bigIntHash(privateKey.N),
AuthorityKeyId: ca.RawSubject,
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(2, 0, 0),
IsCA: false,
BasicConstraintsValid: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
DNSNames: dnsNames,
IPAddresses: ips,
}
// Sign the certificate
cert_b, err := x509.CreateCertificate(rand.Reader, &template, ca, pubKey, catls.PrivateKey)
// Public key
certOut, err := os.Create(filepath.Join(outCertDirectory, "bumper.crt"))
if err != nil {
log.Fatalf("Create bumper.crt failed: %v", err)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cert_b})
certOut.Close()
log.Printf("bumper.crt created at %v\n", filepath.Join(outCertDirectory, "bumper.crt"))
// Private key
keyOut, err := os.OpenFile(filepath.Join(outCertDirectory, "bumper.key"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("create bumper.key failed: %v", err)
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
keyOut.Close()
log.Printf("bumper.key created at %v\n", filepath.Join(outCertDirectory, "bumper.key"))
}
func bigIntHash(n *big.Int) []byte {
h := sha1.New()
h.Write(n.Bytes())
return h.Sum(nil)
}
// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}
// pathexistsType checks if a path exists and is a file or directory
func pathExistsType(filename string) (exists bool, isfile bool) {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false, false
}
return true, !info.IsDir()
}

View file

@ -1,41 +0,0 @@
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

@ -8,7 +8,6 @@ Users can generate certificates in the following ways:
| Method | Description | | Method | Description |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| [Create_Certs](#creating-certs-using-createcerts) | ***(Preferred)*** This is a utility that has been created to assist in generating the certificates required easily. |
| [OpenSSL](#manually-create-certs-with-openssl) | Users can manually create the same certificates as Create_Certs by utilizing OpenSSL. | | [OpenSSL](#manually-create-certs-with-openssl) | Users can manually create the same certificates as Create_Certs by utilizing OpenSSL. |
| [Custom CA/Self](#using-a-custom-caself) | If a user has their own CA the certificates can be generated there and used within Bumper. | | [Custom CA/Self](#using-a-custom-caself) | If a user has their own CA the certificates can be generated there and used within Bumper. |
@ -17,39 +16,9 @@ Users can generate certificates in the following ways:
* A CA Cert must be provided that can be imported into devices (phones, browsers, etc). * A CA Cert must be provided that can be imported into devices (phones, browsers, etc).
* Server certificate should include [SANs (Subject Alternate Names)](#subject-alternative-name) for all of the *.ecovacs, etc domains. * Server certificate should include [SANs (Subject Alternate Names)](#subject-alternative-name) for all of the *.ecovacs, etc domains.
## Creating certs using Create_Certs
Create_Certs was created to ease creation of certificates specifically for Bumper. Binaries are provided for Windows/Linux/OSX/RPi (ARMv5) in the Create_Certs directory.
| Binary | Platform |
| ------------------------ | -------------------- |
| create_certs_linux | Linux |
| create_certs_osx | macOS/x |
| create_certs_windows.exe | Windows |
| create_certs_rpi | RaspberryPi (ARM v5) |
Create_Certs is written in Go which allows cross-platform compiling. If the binaries don't work on your platform, install Go.
With Go installed you can:
* Execute the go code - `go run create_certs/src/create_certs.go`
* Build a new binary for your platform - `go build create_certs/src/create_certs.go`
### Usage
Create_Certs will automatically create the required certificates in the directory it is executed from. For best results change to the {bumper_home}/certs directory prior to executing, otherwise you'll need to move the certs after.
1. `cd certs`
2. Execute create_certs (using the binary fitting your platform) - `../create_certs/create_certs_{platform}`
3. The certificates are generated and should be available in the current directory (certs)
## Subject Alternative Name
The server certificate requires a number of SAN (Subject Alternative Names) be added. Create_Certs handles this automatically by loading any SANs listed in the `create_certs/Bumper_SAN.txt` file. If creating certificates manually via OpenSSl/Custom CA these will need to be added.
## Manually create certs with OpenSSL ## Manually create certs with OpenSSL
I get it, you don't trust create_certs and want to do it manually. The easiest way to create the required certs is at https://certificatetools.com/. In fact the below OpenSSL commands come straight from that site, post creation via the GUI. The easiest way to create the required certs is at https://certificatetools.com/. In fact the below OpenSSL commands come straight from that site, post creation via the GUI.
### Create a Root CA ### Create a Root CA
@ -179,4 +148,4 @@ DNS.9 = *.area.ww.ecouser.net
## Using a Custom CA/Self ## Using a Custom CA/Self
This should work siimilar to the OpenSSL method. Ensure the server certificate has the proper [SANs](#subject-alternative-name) in place. This should work siimilar to the OpenSSL method. Ensure the server certificate has the proper SANs (see above) in place.

View file

@ -1,16 +1,6 @@
import mock
from mock import patch from mock import patch
import pytest
from tinydb.storages import MemoryStorage
from tinydb import TinyDB, Query
import bumper import bumper
import os
import datetime, time
import platform
import json
import asyncio
from testfixtures import LogCapture
import sys
def mock_subrun(*args): def mock_subrun(*args):
@ -40,63 +30,3 @@ def test_argparse(mock_start):
assert bumper.bumper_announce_ip == "127.0.0.1" assert bumper.bumper_announce_ip == "127.0.0.1"
assert bumper.bumper_listen == "127.0.0.1" assert bumper.bumper_listen == "127.0.0.1"
assert mock_start.called == True assert mock_start.called == True
@patch("subprocess.run")
@patch("platform.system")
@patch("platform.machine")
@patch("os.execv")
def test_createcert(mock_run, mock_platform, mock_machine, mock_exec):
mock_run.side_effect = mock_subrun
platform.system.return_value = "darwin"
bumper.create_certs()
assert mock_run.called == True
assert (
os.path.join("..", "create_certs", "create_certs_osx")
in mock_exec.call_args.args[0]
)
platform.system.return_value = "windows"
bumper.create_certs()
assert mock_run.called == True
assert (
os.path.join("..", "create_certs", "create_certs_windows.exe")
in mock_exec.call_args.args[0]
)
platform.system.return_value = "linux"
bumper.create_certs()
assert mock_run.called == True
assert (
os.path.join("..", "create_certs", "create_certs_linux")
in mock_exec.call_args.args[0]
)
platform.system.return_value = "linux"
platform.machine.return_value = "arm"
bumper.create_certs()
assert mock_run.called == True
assert (
os.path.join("..", "create_certs", "create_certs_rpi")
in mock_exec.call_args.args[0]
)
with LogCapture() as l:
platform.system.return_value = "nixbad"
bumper.create_certs()
l.check_present(
(
"root",
"CRITICAL",
"Can't determine platform. Create certs manually and try again.",
)
)
@patch("bumper.first_run")
def test_main(mock_firstrun):
bumper.ca_cert = "sf"
bumper.main()
assert mock_firstrun.called == True
bumper.ca_cert = "tests/test_certs/ca.crt"