refactor goinstaller to prepare for code signing
This commit is contained in:
parent
9af5c9ead9
commit
258261dc64
|
@ -1,7 +1,6 @@
|
|||
FROM python:3.9.2-slim
|
||||
|
||||
ENV TACTICAL_DIR /opt/tactical
|
||||
ENV TACTICAL_GO_DIR /usr/local/rmmgo
|
||||
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
|
||||
ENV WORKSPACE_DIR /workspace
|
||||
ENV TACTICAL_USER tactical
|
||||
|
@ -14,9 +13,6 @@ EXPOSE 8000
|
|||
RUN groupadd -g 1000 tactical && \
|
||||
useradd -u 1000 -g 1000 tactical
|
||||
|
||||
# Copy Go Files
|
||||
COPY --from=golang:1.16 /usr/local/go ${TACTICAL_GO_DIR}/go
|
||||
|
||||
# Copy Dev python reqs
|
||||
COPY ./requirements.txt /
|
||||
|
||||
|
|
|
@ -150,9 +150,6 @@ EOF
|
|||
fi
|
||||
|
||||
if [ "$1" = 'tactical-api' ]; then
|
||||
cp "${WORKSPACE_DIR}"/api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo
|
||||
chmod +x /usr/local/bin/goversioninfo
|
||||
|
||||
check_tactical_ready
|
||||
"${VIRTUAL_ENV}"/bin/python manage.py runserver 0.0.0.0:"${API_PORT}"
|
||||
fi
|
||||
|
|
|
@ -363,8 +363,7 @@ class TestAgentViews(TacticalTestCase):
|
|||
self.check_not_authenticated("patch", url)
|
||||
|
||||
@patch("os.path.exists")
|
||||
@patch("subprocess.run")
|
||||
def test_install_agent(self, mock_subprocess, mock_file_exists):
|
||||
def test_install_agent(self, mock_file_exists):
|
||||
url = f"/agents/installagent/"
|
||||
|
||||
site = baker.make("clients.Site")
|
||||
|
@ -382,29 +381,20 @@ class TestAgentViews(TacticalTestCase):
|
|||
}
|
||||
|
||||
mock_file_exists.return_value = False
|
||||
mock_subprocess.return_value.returncode = 0
|
||||
r = self.client.post(url, data, format="json")
|
||||
self.assertEqual(r.status_code, 406)
|
||||
|
||||
mock_file_exists.return_value = True
|
||||
mock_subprocess.return_value.returncode = 1
|
||||
r = self.client.post(url, data, format="json")
|
||||
self.assertEqual(r.status_code, 413)
|
||||
|
||||
mock_file_exists.return_value = True
|
||||
mock_subprocess.return_value.returncode = 0
|
||||
r = self.client.post(url, data, format="json")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
data["arch"] = "32"
|
||||
mock_subprocess.return_value.returncode = 0
|
||||
mock_file_exists.return_value = False
|
||||
r = self.client.post(url, data, format="json")
|
||||
self.assertEqual(r.status_code, 415)
|
||||
|
||||
data["installMethod"] = "manual"
|
||||
data["arch"] = "64"
|
||||
mock_subprocess.return_value.returncode = 0
|
||||
mock_file_exists.return_value = True
|
||||
r = self.client.post(url, data, format="json")
|
||||
self.assertIn("rdp", r.json()["cmd"])
|
||||
|
|
|
@ -14,12 +14,11 @@ from rest_framework.decorators import api_view
|
|||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from core.models import CoreSettings, CustomField
|
||||
from core.models import CoreSettings
|
||||
from logs.models import AuditLog, PendingAction
|
||||
from scripts.models import Script
|
||||
from scripts.tasks import handle_bulk_command_task, handle_bulk_script_task
|
||||
from tacticalrmm.utils import (
|
||||
generate_installer_exe,
|
||||
get_default_timezone,
|
||||
notify_error,
|
||||
reload_nats,
|
||||
|
@ -381,26 +380,21 @@ def install_agent(request):
|
|||
f"winagent-v{version}.exe" if arch == "64" else f"winagent-v{version}-x86.exe"
|
||||
)
|
||||
download_url = settings.DL_64 if arch == "64" else settings.DL_32
|
||||
goarch = "amd64" if arch == "64" else "386"
|
||||
|
||||
_, token = AuthToken.objects.create(
|
||||
user=request.user, expiry=dt.timedelta(hours=request.data["expires"])
|
||||
)
|
||||
|
||||
if request.data["installMethod"] == "exe":
|
||||
return generate_installer_exe(
|
||||
file_name="rmm-installer.exe",
|
||||
goarch="amd64" if arch == "64" else "386",
|
||||
inno=inno,
|
||||
api=request.data["api"],
|
||||
client_id=client_id,
|
||||
site_id=site_id,
|
||||
atype=request.data["agenttype"],
|
||||
rdp=request.data["rdp"],
|
||||
ping=request.data["ping"],
|
||||
power=request.data["power"],
|
||||
download_url=download_url,
|
||||
token=token,
|
||||
)
|
||||
ret = {
|
||||
"token": token,
|
||||
"url": download_url,
|
||||
"inno": inno,
|
||||
"goarch": goarch,
|
||||
"genurl": settings.EXE_GEN_URL,
|
||||
}
|
||||
return Response(ret)
|
||||
|
||||
elif request.data["installMethod"] == "manual":
|
||||
cmd = [
|
||||
|
|
|
@ -11,8 +11,8 @@ from rest_framework.response import Response
|
|||
from rest_framework.views import APIView
|
||||
|
||||
from agents.models import Agent
|
||||
from core.models import CoreSettings, CustomField
|
||||
from tacticalrmm.utils import generate_installer_exe, notify_error
|
||||
from core.models import CoreSettings
|
||||
from tacticalrmm.utils import notify_error
|
||||
|
||||
from .models import Client, ClientCustomField, Deployment, Site, SiteCustomField
|
||||
from .serializers import (
|
||||
|
@ -278,6 +278,10 @@ class GenerateAgent(APIView):
|
|||
permission_classes = (AllowAny,)
|
||||
|
||||
def get(self, request, uid):
|
||||
import requests
|
||||
import tempfile
|
||||
from django.http import FileResponse
|
||||
|
||||
try:
|
||||
_ = uuid.UUID(uid, version=4)
|
||||
except ValueError:
|
||||
|
@ -295,18 +299,36 @@ class GenerateAgent(APIView):
|
|||
client = re.sub(r"([^a-zA-Z0-9]+)", "", client)
|
||||
site = re.sub(r"([^a-zA-Z0-9]+)", "", site)
|
||||
ext = ".exe" if d.arch == "64" else "-x86.exe"
|
||||
file_name = f"rmm-{client}-{site}-{d.mon_type}{ext}"
|
||||
|
||||
return generate_installer_exe(
|
||||
file_name=f"rmm-{client}-{site}-{d.mon_type}{ext}",
|
||||
goarch="amd64" if d.arch == "64" else "386",
|
||||
inno=inno,
|
||||
api=f"https://{request.get_host()}",
|
||||
client_id=d.client.pk,
|
||||
site_id=d.site.pk,
|
||||
atype=d.mon_type,
|
||||
rdp=d.install_flags["rdp"],
|
||||
ping=d.install_flags["ping"],
|
||||
power=d.install_flags["power"],
|
||||
download_url=settings.DL_64 if d.arch == "64" else settings.DL_32,
|
||||
token=d.token_key,
|
||||
)
|
||||
data = {
|
||||
"client": d.client.pk,
|
||||
"site": d.site.pk,
|
||||
"agenttype": d.mon_type,
|
||||
"rdp": str(d.install_flags["rdp"]),
|
||||
"ping": str(d.install_flags["ping"]),
|
||||
"power": str(d.install_flags["power"]),
|
||||
"goarch": "amd64" if d.arch == "64" else "386",
|
||||
"token": d.token_key,
|
||||
"inno": inno,
|
||||
"url": settings.DL_64 if d.arch == "64" else settings.DL_32,
|
||||
"api": f"https://{request.get_host()}",
|
||||
}
|
||||
headers = {"Content-type": "application/json"}
|
||||
|
||||
with tempfile.NamedTemporaryFile() as fp:
|
||||
r = requests.post(
|
||||
settings.EXE_GEN_URL,
|
||||
json=data,
|
||||
headers=headers,
|
||||
stream=True,
|
||||
)
|
||||
with open(fp.name, "wb") as f:
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
del r
|
||||
response = FileResponse(
|
||||
open(fp.name, "rb"), as_attachment=True, filename=file_name
|
||||
)
|
||||
return response
|
||||
|
|
Binary file not shown.
|
@ -1,5 +0,0 @@
|
|||
module github.com/wh1te909/goinstaller
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/josephspurrier/goversioninfo v1.2.0 // indirect
|
|
@ -1,10 +0,0 @@
|
|||
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
|
||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/josephspurrier/goversioninfo v1.2.0 h1:tpLHXAxLHKHg/dCU2AAYx08A4m+v9/CWg6+WUvTF4uQ=
|
||||
github.com/josephspurrier/goversioninfo v1.2.0/go.mod h1:AGP2a+Y/OVJZ+s6XM4IwFUpkETwvn0orYurY8qpw1+0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="TacticalRMMInstaller"
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="*"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel
|
||||
level="requireAdministrator"
|
||||
uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
|
@ -1,186 +0,0 @@
|
|||
//go:generate goversioninfo -icon=onit.ico -manifest=goversioninfo.exe.manifest -gofile=versioninfo.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Inno string
|
||||
Api string
|
||||
Client string
|
||||
Site string
|
||||
Atype string
|
||||
Power string
|
||||
Rdp string
|
||||
Ping string
|
||||
Token string
|
||||
DownloadUrl string
|
||||
)
|
||||
|
||||
var netTransport = &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
var netClient = &http.Client{
|
||||
Timeout: time.Second * 900,
|
||||
Transport: netTransport,
|
||||
}
|
||||
|
||||
func downloadAgent(filepath string) (err error) {
|
||||
|
||||
out, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
resp, err := netClient.Get(DownloadUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("Bad response: %s", resp.Status)
|
||||
}
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
debugLog := flag.String("log", "", "Verbose output")
|
||||
localMesh := flag.String("local-mesh", "", "Use local mesh agent")
|
||||
silent := flag.Bool("silent", false, "Do not popup any message boxes during installation")
|
||||
cert := flag.String("cert", "", "Path to ca.pem")
|
||||
flag.Parse()
|
||||
|
||||
var debug bool = false
|
||||
|
||||
if strings.TrimSpace(strings.ToLower(*debugLog)) == "debug" {
|
||||
debug = true
|
||||
}
|
||||
|
||||
agentBinary := filepath.Join(os.Getenv("windir"), "Temp", Inno)
|
||||
tacrmm := filepath.Join(os.Getenv("PROGRAMFILES"), "TacticalAgent", "tacticalrmm.exe")
|
||||
|
||||
cmdArgs := []string{
|
||||
"-m", "install", "--api", Api, "--client-id",
|
||||
Client, "--site-id", Site, "--agent-type", Atype,
|
||||
"--auth", Token,
|
||||
}
|
||||
|
||||
if debug {
|
||||
cmdArgs = append(cmdArgs, "-log", "debug")
|
||||
}
|
||||
|
||||
if *silent {
|
||||
cmdArgs = append(cmdArgs, "-silent")
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(*localMesh)) != 0 {
|
||||
cmdArgs = append(cmdArgs, "-local-mesh", *localMesh)
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(*cert)) != 0 {
|
||||
cmdArgs = append(cmdArgs, "-cert", *cert)
|
||||
}
|
||||
|
||||
if Rdp == "1" {
|
||||
cmdArgs = append(cmdArgs, "-rdp")
|
||||
}
|
||||
|
||||
if Ping == "1" {
|
||||
cmdArgs = append(cmdArgs, "-ping")
|
||||
}
|
||||
|
||||
if Power == "1" {
|
||||
cmdArgs = append(cmdArgs, "-power")
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println("Installer:", agentBinary)
|
||||
fmt.Println("Tactical Agent:", tacrmm)
|
||||
fmt.Println("Download URL:", DownloadUrl)
|
||||
fmt.Println("Install command:", tacrmm, strings.Join(cmdArgs, " "))
|
||||
}
|
||||
|
||||
fmt.Println("Downloading agent...")
|
||||
dl := downloadAgent(agentBinary)
|
||||
if dl != nil {
|
||||
fmt.Println("ERROR: unable to download agent from", DownloadUrl)
|
||||
fmt.Println(dl)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer os.Remove(agentBinary)
|
||||
|
||||
fmt.Println("Extracting files...")
|
||||
winagentCmd := exec.Command(agentBinary, "/VERYSILENT", "/SUPPRESSMSGBOXES")
|
||||
err := winagentCmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
fmt.Println("Installation starting.")
|
||||
cmd := exec.Command(tacrmm, cmdArgs...)
|
||||
|
||||
cmdReader, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
|
||||
cmdErrReader, oerr := cmd.StderrPipe()
|
||||
if oerr != nil {
|
||||
fmt.Fprintln(os.Stderr, oerr)
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(cmdReader)
|
||||
escanner := bufio.NewScanner(cmdErrReader)
|
||||
go func() {
|
||||
for scanner.Scan() {
|
||||
fmt.Println(scanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for escanner.Scan() {
|
||||
fmt.Println(escanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"FixedFileInfo": {
|
||||
"FileVersion": {
|
||||
"Major": 1,
|
||||
"Minor": 0,
|
||||
"Patch": 0,
|
||||
"Build": 0
|
||||
},
|
||||
"ProductVersion": {
|
||||
"Major": 1,
|
||||
"Minor": 0,
|
||||
"Patch": 0,
|
||||
"Build": 0
|
||||
},
|
||||
"FileFlagsMask": "3f",
|
||||
"FileFlags ": "00",
|
||||
"FileOS": "040004",
|
||||
"FileType": "01",
|
||||
"FileSubType": "00"
|
||||
},
|
||||
"StringFileInfo": {
|
||||
"Comments": "",
|
||||
"CompanyName": "Tactical Techs",
|
||||
"FileDescription": "Tactical RMM Installer",
|
||||
"FileVersion": "v1.0.0.0",
|
||||
"InternalName": "rmm.exe",
|
||||
"LegalCopyright": "Copyright (c) 2020 Tactical Techs",
|
||||
"LegalTrademarks": "",
|
||||
"OriginalFilename": "installer.go",
|
||||
"PrivateBuild": "",
|
||||
"ProductName": "Tactical RMM Installer",
|
||||
"ProductVersion": "v1.0.0.0",
|
||||
"SpecialBuild": ""
|
||||
},
|
||||
"VarFileInfo": {
|
||||
"Translation": {
|
||||
"LangID": "0409",
|
||||
"CharsetID": "04B0"
|
||||
}
|
||||
},
|
||||
"IconPath": "",
|
||||
"ManifestPath": ""
|
||||
}
|
|
@ -33,6 +33,8 @@ NPM_VER = "11"
|
|||
DL_64 = f"https://github.com/wh1te909/rmmagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}.exe"
|
||||
DL_32 = f"https://github.com/wh1te909/rmmagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}-x86.exe"
|
||||
|
||||
EXE_GEN_URL = "https://exe.tacticalrmm.io/api/v1/exe"
|
||||
|
||||
try:
|
||||
from .local_settings import *
|
||||
except ImportError:
|
||||
|
|
|
@ -3,11 +3,9 @@ import os
|
|||
import string
|
||||
import subprocess
|
||||
import time
|
||||
from typing import Union
|
||||
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from loguru import logger
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
|
@ -31,130 +29,6 @@ WEEK_DAYS = {
|
|||
}
|
||||
|
||||
|
||||
def generate_installer_exe(
|
||||
file_name: str,
|
||||
goarch: str,
|
||||
inno: str,
|
||||
api: str,
|
||||
client_id: int,
|
||||
site_id: int,
|
||||
atype: str,
|
||||
rdp: int,
|
||||
ping: int,
|
||||
power: int,
|
||||
download_url: str,
|
||||
token: str,
|
||||
) -> Union[Response, HttpResponse]:
|
||||
|
||||
go_bin = "/usr/local/rmmgo/go/bin/go"
|
||||
if not os.path.exists(go_bin):
|
||||
return Response("nogolang", status=status.HTTP_409_CONFLICT)
|
||||
|
||||
exe = os.path.join(settings.EXE_DIR, file_name)
|
||||
if os.path.exists(exe):
|
||||
try:
|
||||
os.remove(exe)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
|
||||
cmd = [
|
||||
"env",
|
||||
"CGO_ENABLED=0",
|
||||
"GOOS=windows",
|
||||
f"GOARCH={goarch}",
|
||||
go_bin,
|
||||
"build",
|
||||
f"-ldflags=\"-s -w -X 'main.Inno={inno}'",
|
||||
f"-X 'main.Api={api}'",
|
||||
f"-X 'main.Client={client_id}'",
|
||||
f"-X 'main.Site={site_id}'",
|
||||
f"-X 'main.Atype={atype}'",
|
||||
f"-X 'main.Rdp={rdp}'",
|
||||
f"-X 'main.Ping={ping}'",
|
||||
f"-X 'main.Power={power}'",
|
||||
f"-X 'main.DownloadUrl={download_url}'",
|
||||
f"-X 'main.Token={token}'\"",
|
||||
"-o",
|
||||
exe,
|
||||
]
|
||||
|
||||
build_error = False
|
||||
gen_error = False
|
||||
|
||||
gen = [
|
||||
"env",
|
||||
"GOOS=windows",
|
||||
"CGO_ENABLED=0",
|
||||
f"GOARCH={goarch}",
|
||||
go_bin,
|
||||
"generate",
|
||||
]
|
||||
|
||||
try:
|
||||
r1 = subprocess.run(
|
||||
" ".join(gen),
|
||||
capture_output=True,
|
||||
shell=True,
|
||||
cwd=os.path.join(settings.BASE_DIR, "core/goinstaller"),
|
||||
)
|
||||
except Exception as e:
|
||||
gen_error = True
|
||||
logger.error(str(e))
|
||||
return Response("genfailed", status=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE)
|
||||
|
||||
if r1.returncode != 0:
|
||||
gen_error = True
|
||||
if r1.stdout:
|
||||
logger.error(r1.stdout.decode("utf-8", errors="ignore"))
|
||||
|
||||
if r1.stderr:
|
||||
logger.error(r1.stderr.decode("utf-8", errors="ignore"))
|
||||
|
||||
logger.error(f"Go build failed with return code {r1.returncode}")
|
||||
|
||||
if gen_error:
|
||||
return Response("genfailed", status=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE)
|
||||
|
||||
try:
|
||||
r = subprocess.run(
|
||||
" ".join(cmd),
|
||||
capture_output=True,
|
||||
shell=True,
|
||||
cwd=os.path.join(settings.BASE_DIR, "core/goinstaller"),
|
||||
)
|
||||
except Exception as e:
|
||||
build_error = True
|
||||
logger.error(str(e))
|
||||
return Response("buildfailed", status=status.HTTP_412_PRECONDITION_FAILED)
|
||||
|
||||
if r.returncode != 0:
|
||||
build_error = True
|
||||
if r.stdout:
|
||||
logger.error(r.stdout.decode("utf-8", errors="ignore"))
|
||||
|
||||
if r.stderr:
|
||||
logger.error(r.stderr.decode("utf-8", errors="ignore"))
|
||||
|
||||
logger.error(f"Go build failed with return code {r.returncode}")
|
||||
|
||||
if build_error:
|
||||
return Response("buildfailed", status=status.HTTP_412_PRECONDITION_FAILED)
|
||||
|
||||
if settings.DEBUG:
|
||||
with open(exe, "rb") as f:
|
||||
response = HttpResponse(
|
||||
f.read(),
|
||||
content_type="application/vnd.microsoft.portable-executable",
|
||||
)
|
||||
response["Content-Disposition"] = f"inline; filename={file_name}"
|
||||
return response
|
||||
else:
|
||||
response = HttpResponse()
|
||||
response["Content-Disposition"] = f"attachment; filename={file_name}"
|
||||
response["X-Accel-Redirect"] = f"/private/exe/{file_name}"
|
||||
return response
|
||||
|
||||
|
||||
def get_default_timezone():
|
||||
from core.models import CoreSettings
|
||||
|
||||
|
|
|
@ -30,17 +30,15 @@ FROM python:3.9.2-slim
|
|||
ENV VIRTUAL_ENV /opt/venv
|
||||
ENV TACTICAL_DIR /opt/tactical
|
||||
ENV TACTICAL_TMP_DIR /tmp/tactical
|
||||
ENV TACTICAL_GO_DIR /usr/local/rmmgo
|
||||
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
|
||||
ENV TACTICAL_USER tactical
|
||||
ENV PATH "${VIRTUAL_ENV}/bin:${TACTICAL_GO_DIR}/go/bin:$PATH"
|
||||
ENV PATH "${VIRTUAL_ENV}/bin:$PATH"
|
||||
|
||||
# copy files from repo
|
||||
COPY api/tacticalrmm ${TACTICAL_TMP_DIR}/api
|
||||
COPY scripts ${TACTICAL_TMP_DIR}/scripts
|
||||
|
||||
# copy go install from build stage
|
||||
COPY --from=golang:1.16 /usr/local/go ${TACTICAL_GO_DIR}/go
|
||||
COPY --from=CREATE_VENV_STAGE ${VIRTUAL_ENV} ${VIRTUAL_ENV}
|
||||
|
||||
# install deps
|
||||
|
@ -48,16 +46,11 @@ RUN apt-get update && \
|
|||
apt-get upgrade -y && \
|
||||
apt-get install -y --no-install-recommends git rsync && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo && \
|
||||
groupadd -g 1000 "${TACTICAL_USER}" && \
|
||||
useradd -M -d "${TACTICAL_DIR}" -s /bin/bash -u 1000 -g 1000 "${TACTICAL_USER}"
|
||||
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
|
||||
# overwrite goversioninfo file
|
||||
COPY api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/goversioninfo
|
||||
RUN chmod +x /usr/local/bin/goversioninfo
|
||||
|
||||
# copy nats-api file
|
||||
COPY natsapi/bin/nats-api /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/nats-api
|
||||
|
|
16
install.sh
16
install.sh
|
@ -181,17 +181,6 @@ CERT_PUB_KEY=/etc/letsencrypt/live/${rootdomain}/fullchain.pem
|
|||
sudo chown ${USER}:${USER} -R /etc/letsencrypt
|
||||
sudo chmod 775 -R /etc/letsencrypt
|
||||
|
||||
print_green 'Installing golang'
|
||||
|
||||
sudo mkdir -p /usr/local/rmmgo
|
||||
go_tmp=$(mktemp -d -t rmmgo-XXXXXXXXXX)
|
||||
wget https://golang.org/dl/go1.16.2.linux-amd64.tar.gz -P ${go_tmp}
|
||||
|
||||
tar -xzf ${go_tmp}/go1.16.2.linux-amd64.tar.gz -C ${go_tmp}
|
||||
|
||||
sudo mv ${go_tmp}/go /usr/local/rmmgo/
|
||||
rm -rf ${go_tmp}
|
||||
|
||||
print_green 'Downloading NATS'
|
||||
|
||||
nats_tmp=$(mktemp -d -t nats-XXXXXXXXXX)
|
||||
|
@ -376,11 +365,6 @@ EOF
|
|||
)"
|
||||
echo "${localvars}" > /rmm/api/tacticalrmm/tacticalrmm/local_settings.py
|
||||
|
||||
/usr/local/rmmgo/go/bin/go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
||||
sudo cp /rmm/api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/goversioninfo
|
||||
sudo chmod +x /usr/local/bin/goversioninfo
|
||||
|
||||
sudo cp /rmm/natsapi/bin/nats-api /usr/local/bin
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-api
|
||||
sudo chmod +x /usr/local/bin/nats-api
|
||||
|
|
15
restore.sh
15
restore.sh
|
@ -103,17 +103,7 @@ fi
|
|||
# prevents logging issues with some VPS providers like Vultr if this is a freshly provisioned instance that hasn't been rebooted yet
|
||||
sudo systemctl restart systemd-journald.service
|
||||
|
||||
print_green 'Installing golang'
|
||||
|
||||
sudo apt update
|
||||
sudo mkdir -p /usr/local/rmmgo
|
||||
go_tmp=$(mktemp -d -t rmmgo-XXXXXXXXXX)
|
||||
wget https://golang.org/dl/go1.16.2.linux-amd64.tar.gz -P ${go_tmp}
|
||||
|
||||
tar -xzf ${go_tmp}/go1.16.2.linux-amd64.tar.gz -C ${go_tmp}
|
||||
|
||||
sudo mv ${go_tmp}/go /usr/local/rmmgo/
|
||||
rm -rf ${go_tmp}
|
||||
|
||||
print_green 'Downloading NATS'
|
||||
|
||||
|
@ -276,11 +266,6 @@ gzip -d $tmp_dir/rmm/debug.log.gz
|
|||
cp $tmp_dir/rmm/debug.log /rmm/api/tacticalrmm/tacticalrmm/private/log/
|
||||
cp $tmp_dir/rmm/mesh*.exe /rmm/api/tacticalrmm/tacticalrmm/private/exe/
|
||||
|
||||
/usr/local/rmmgo/go/bin/go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
||||
sudo cp /rmm/api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/goversioninfo
|
||||
sudo chmod +x /usr/local/bin/goversioninfo
|
||||
|
||||
sudo cp /rmm/natsapi/bin/nats-api /usr/local/bin
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-api
|
||||
sudo chmod +x /usr/local/bin/nats-api
|
||||
|
|
19
update.sh
19
update.sh
|
@ -121,20 +121,6 @@ if ! [[ $CHECK_NGINX_WORKER_CONN ]]; then
|
|||
sudo sed -i 's/worker_connections.*/worker_connections 2048;/g' /etc/nginx/nginx.conf
|
||||
fi
|
||||
|
||||
CHECK_HAS_GO116=$(/usr/local/rmmgo/go/bin/go version | grep go1.16.2)
|
||||
if ! [[ $CHECK_HAS_GO116 ]]; then
|
||||
printf >&2 "${GREEN}Updating golang to version 1.16.2${NC}\n"
|
||||
sudo rm -rf /home/${USER}/go/
|
||||
sudo rm -rf /usr/local/rmmgo/
|
||||
sudo mkdir -p /usr/local/rmmgo
|
||||
go_tmp=$(mktemp -d -t rmmgo-XXXXXXXXXX)
|
||||
wget https://golang.org/dl/go1.16.2.linux-amd64.tar.gz -P ${go_tmp}
|
||||
tar -xzf ${go_tmp}/go1.16.2.linux-amd64.tar.gz -C ${go_tmp}
|
||||
sudo mv ${go_tmp}/go /usr/local/rmmgo/
|
||||
rm -rf ${go_tmp}
|
||||
sudo chown -R $USER:$GROUP /home/${USER}/.cache
|
||||
fi
|
||||
|
||||
HAS_PY39=$(which python3.9)
|
||||
if ! [[ $HAS_PY39 ]]; then
|
||||
printf >&2 "${GREEN}Updating to Python 3.9${NC}\n"
|
||||
|
@ -212,11 +198,6 @@ EOF
|
|||
echo "${adminenabled}" | tee --append /rmm/api/tacticalrmm/tacticalrmm/local_settings.py > /dev/null
|
||||
fi
|
||||
|
||||
/usr/local/rmmgo/go/bin/go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
||||
sudo cp /rmm/api/tacticalrmm/core/goinstaller/bin/goversioninfo /usr/local/bin/
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/goversioninfo
|
||||
sudo chmod +x /usr/local/bin/goversioninfo
|
||||
|
||||
sudo cp /rmm/natsapi/bin/nats-api /usr/local/bin
|
||||
sudo chown ${USER}:${USER} /usr/local/bin/nats-api
|
||||
sudo chmod +x /usr/local/bin/nats-api
|
||||
|
|
|
@ -189,29 +189,38 @@ export default {
|
|||
this.arch === "64"
|
||||
? `rmm-${clientStripped}-${siteStripped}-${this.agenttype}.exe`
|
||||
: `rmm-${clientStripped}-${siteStripped}-${this.agenttype}-x86.exe`;
|
||||
|
||||
this.$axios
|
||||
.post("/agents/installagent/", data, { responseType: "blob" })
|
||||
.post("/agents/installagent/", data)
|
||||
.then(r => {
|
||||
this.$q.loading.hide();
|
||||
const blob = new Blob([r.data], { type: "application/vnd.microsoft.portable-executable" });
|
||||
let link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = fileName;
|
||||
link.click();
|
||||
this.showDLMessage();
|
||||
const newData = {
|
||||
client: this.client.value,
|
||||
site: this.site.value,
|
||||
agenttype: this.agenttype,
|
||||
power: this.power ? "1" : "0",
|
||||
rdp: this.rdp ? "1" : "0",
|
||||
ping: this.ping ? "1" : "0",
|
||||
goarch: r.data.goarch,
|
||||
token: r.data.token,
|
||||
inno: r.data.inno,
|
||||
url: r.data.url,
|
||||
api,
|
||||
};
|
||||
|
||||
this.$axios.post(r.data.genurl, newData, { responseType: "blob" }).then(r => {
|
||||
this.$q.loading.hide();
|
||||
const blob = new Blob([r.data], { type: "application/vnd.microsoft.portable-executable" });
|
||||
let link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = fileName;
|
||||
link.click();
|
||||
this.showDLMessage();
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
this.$q.loading.hide();
|
||||
let err;
|
||||
switch (e.response.status) {
|
||||
case 409:
|
||||
err = "Golang is not installed";
|
||||
break;
|
||||
case 412:
|
||||
err = "Golang build failed. Check debug log for the error message";
|
||||
break;
|
||||
case 413:
|
||||
err = "Golang generate failed. Check debug log for the error message";
|
||||
break;
|
||||
case 406:
|
||||
err = "Missing 64 bit meshagent.exe. Upload it from File > Upload Mesh Agent";
|
||||
break;
|
||||
|
@ -219,9 +228,8 @@ export default {
|
|||
err = "Missing 32 bit meshagent-x86.exe. Upload it from File > Upload Mesh Agent";
|
||||
break;
|
||||
default:
|
||||
err = "Something went wrong";
|
||||
err = e.response.data;
|
||||
}
|
||||
this.$q.loading.hide();
|
||||
this.notifyError(err, 4000);
|
||||
});
|
||||
} else if (this.installMethod === "powershell") {
|
||||
|
|
Loading…
Reference in New Issue