fix agent update, new agent 0.11.1

This commit is contained in:
wh1te909
2020-09-14 03:29:46 +00:00
parent f62f3500c4
commit bf497886be
6 changed files with 125 additions and 74 deletions

View File

@@ -145,6 +145,62 @@ def install_updates():
return __salt__["cmd.run_bg"]([TAC_RMM, "-m", "winupdater"])
def agent_update_v2(inno, url):
# make sure another instance of the update is not running
# this function spawns 2 instances of itself (because we call it twice with salt run_bg)
# so if more than 2 running, don't continue as an update is already running
count = 0
for p in psutil.process_iter():
try:
with p.oneshot():
if "win_agent.agent_update_v2" in p.cmdline():
count += 1
except Exception:
continue
if count > 2:
return "already running"
sleep(random.randint(1, 20)) # don't flood the rmm
exe = os.path.join(TEMP_DIR, inno)
if os.path.exists(exe):
try:
os.remove(exe)
except:
pass
try:
r = requests.get(url, stream=True, timeout=600)
except Exception:
return "failed"
if r.status_code != 200:
return "failed"
with open(exe, "wb") as f:
for chunk in r.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
del r
ret = subprocess.run([exe, "/VERYSILENT", "/SUPPRESSMSGBOXES"], timeout=90)
return "ok"
def do_agent_update_v2(inno, url):
return __salt__["cmd.run_bg"](
[
SALT_CALL,
"win_agent.agent_update_v2",
f"inno={inno}",
f"url={url}",
"--local",
]
)
def agent_update(version, url):
# make sure another instance of the update is not running
# this function spawns 2 instances of itself so if more than 2 running,

View File

@@ -19,48 +19,38 @@ logger.configure(**settings.LOG_CONFIG)
@app.task
def send_agent_update_task(pks, version):
assert isinstance(pks, list)
ver = version.split("winagent-v")[1]
q = Agent.objects.only("pk").filter(pk__in=pks)
agents = [
i
for i in q
if pyver.parse(i.version) < pyver.parse(ver) and i.status == "online"
]
q = Agent.objects.filter(pk__in=pks)
agents = [i.pk for i in q if pyver.parse(i.version) < pyver.parse(version)]
if agents:
for agent in agents:
agent.update_pending = True
agent.save(update_fields=["update_pending"])
chunks = (agents[i : i + 30] for i in range(0, len(agents), 30))
minions = [i.salt_id for i in agents]
for chunk in chunks:
for pk in chunk:
agent = Agent.objects.get(pk=pk)
if agent.operating_system is not None:
if "64bit" in agent.operating_system:
arch = "64"
elif "32bit" in agent.operating_system:
arch = "32"
else:
arch = "64"
r = Agent.get_github_versions()
git_versions = r["versions"]
data = r["data"] # full response from github
versions = {}
url = settings.DL_64 if arch == "64" else settings.DL_32
inno = (
f"winagent-v{version}.exe"
if arch == "64"
else f"winagent-v{version}-x86.exe"
)
for i, release in enumerate(data):
versions[i] = release["name"]
key = [k for k, v in versions.items() if v == version][0]
# download_url = data[key]["assets"][1]["browser_download_url"]
# emergency patch for now until fix tomorrow, otherwise all 64 bit agents
# will get 32 bit agents and crash
download_url = "https://github.com/wh1te909/winagent/releases/download/v0.11.0/winagent-v0.11.0.exe"
# split into chunks to not overload salt
chunks = (minions[i : i + 30] for i in range(0, len(minions), 30))
for chunk in chunks:
r = Agent.salt_batch_async(
minions=chunk,
func="win_agent.do_agent_update",
kwargs={"version": ver, "url": download_url},
)
sleep(5)
r = agent.salt_api_async(
func="win_agent.do_agent_update_v2",
kwargs={
"inno": inno,
"url": url,
},
)
sleep(10)
@app.task

View File

@@ -46,11 +46,9 @@ logger.configure(**settings.LOG_CONFIG)
@api_view()
def get_agent_versions(request):
agents = Agent.objects.only("pk")
ret = Agent.get_github_versions()
return Response(
{
"versions": ret["versions"],
"github": ret["data"],
"versions": [settings.LATEST_AGENT_VER],
"agents": AgentHostnameSerializer(agents, many=True).data,
}
)
@@ -325,9 +323,7 @@ def install_agent(request):
inno = (
f"winagent-v{version}.exe" if arch == "64" else f"winagent-v{version}-x86.exe"
)
download_url = (
f"https://github.com/wh1te909/winagent/releases/download/v{version}/{inno}"
)
download_url = settings.DL_64 if arch == "64" else settings.DL_32
_, token = AuthToken.objects.create(
user=request.user, expiry=dt.timedelta(hours=request.data["expires"])

View File

@@ -59,26 +59,13 @@ func main() {
localMesh := flag.String("local-mesh", "", "Use local mesh agent")
flag.Parse()
var debug bool = false
if strings.TrimSpace(*debugLog) == "DEBUG" {
debug = true
}
agentBinary := filepath.Join(os.Getenv("windir"), "Temp", Inno)
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)
}
fmt.Println("Extracting files...")
winagentCmd := exec.Command(agentBinary, "/VERYSILENT", "/SUPPRESSMSGBOXES")
err := winagentCmd.Run()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
time.Sleep(20 * time.Second)
tacrmm := filepath.Join(os.Getenv("PROGRAMFILES"), "TacticalAgent", "tacticalrmm.exe")
cmdArgs := []string{
@@ -88,7 +75,7 @@ func main() {
"--auth", Token,
}
if strings.TrimSpace(*debugLog) == "DEBUG" {
if debug {
cmdArgs = append(cmdArgs, "--log", "DEBUG")
}
@@ -112,6 +99,31 @@ func main() {
cmdArgs = append(cmdArgs, "--power")
}
if debug {
fmt.Println("Installer:", agentBinary)
fmt.Println("Tactical Agent:", tacrmm)
fmt.Println("Download URL:", DownloadUrl)
fmt.Println("Install command:", "cmd.exe", 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)
}
fmt.Println("Extracting files...")
winagentCmd := exec.Command(agentBinary, "/VERYSILENT", "/SUPPRESSMSGBOXES")
err := winagentCmd.Run()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
time.Sleep(20 * time.Second)
fmt.Println("Installation starting.")
cmd := exec.Command("cmd.exe", cmdArgs...)

View File

@@ -11,12 +11,15 @@ AUTH_USER_MODEL = "accounts.User"
# bump this version everytime vue code is changed
# to alert user they need to manually refresh their browser
APP_VER = "0.0.47"
APP_VER = "0.0.48"
# https://github.com/wh1te909/salt
LATEST_SALT_VER = "1.1.0"
LATEST_AGENT_VER = "0.11.0"
LATEST_AGENT_VER = "0.11.1"
DL_64 = f"https://github.com/wh1te909/winagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}.exe"
DL_32 = f"https://github.com/wh1te909/winagent/releases/download/v{LATEST_AGENT_VER}/winagent-v{LATEST_AGENT_VER}-x86.exe"
try:
from .local_settings import *

View File

@@ -10,14 +10,7 @@
<q-separator />
<q-card-section>
Select Version
<q-select
square
dense
options-dense
outlined
v-model="version"
:options="Object.values(versions)"
/>
<q-select square disable dense options-dense outlined v-model="version" :options="versions" />
</q-card-section>
<q-card-section v-show="version !== null">
Select Agent
@@ -41,7 +34,7 @@ export default {
mixins: [mixins],
data() {
return {
versions: {},
versions: [],
version: null,
agents: [],
group: [],
@@ -58,6 +51,7 @@ export default {
.get("/agents/getagentversions/")
.then(r => {
this.versions = r.data.versions;
this.version = r.data.versions[0];
this.agents = r.data.agents;
this.$q.loading.hide();
})