Python moto fails to match valid Eventbridge pattern - aws-event-bridge

I have a couple of Eventbridge events ({"root": "child"} and {"root": ["child"]}) which I want to match against pattern {"root": ["child"]}.
Both these matches are valid according to aws events test-event-pattern -
aws events test-event-pattern --event '{"id": 1234567890, "source": "my-source", "detail-type": "my-detail-type", "detail": {"root": "child"}, "account": 1234567890, "region": "eu-west-1", "time": "1970-12-20T20:00:00Z"}' --event-pattern '{"source": ["my-source"], "detail": {"root": ["child"]}}' --output text
True
aws events test-event-pattern --event '{"id": 1234567890, "source": "my-source", "detail-type": "my-detail-type", "detail": {"root": ["child"]}, "account": 1234567890, "region": "eu-west-1", "time": "1970-12-20T20:00:00Z"}' --event-pattern '{"source": ["my-source"], "detail": {"root": ["child"]}}' --output text
True
But I can only get the former pattern to match when I use moto to mock the message flow (script at bottom)
% python scripts/demo/moto_events/test_moto.py
{"root": "child"} -> True
{"root": ["child"]} -> False
Have I made a mistake here or is moto events behaviour diverging from AWS Eventbridge ?
TIA
cc #BertBlommers
ps using moto 2.0.11
from moto import mock_events, mock_sqs
from botocore.exceptions import ClientError
import boto3, copy, json, yaml
EventBase=yaml.safe_load("""
Source: my-source
DetailType: my-detail-type
""")
Statement=yaml.safe_load("""
Effect: Allow
Principal:
Service: events.amazonaws.com
Action: "sqs:SendMessage"
Resource: "*"
""")
def drain_sqs(sqs, queueurl, nmax=100):
messages, count = [], 0
while True:
resp=sqs.receive_message(QueueUrl=queueurl)
if ("Messages" not in resp or
count > nmax):
break
messages+=resp["Messages"]
count+=1
return messages
#mock_events
#mock_sqs
def test_event_pattern(detail,
eventbase=EventBase,
statement=Statement):
events, sqs, = boto3.client("events"), boto3.client("sqs")
policy=json.dumps({"Version": "2012-10-17",
"Statement": [statement]})
queue=sqs.create_queue(QueueName="my-queue",
Attributes={"Policy": policy})
queueurl=queue["QueueUrl"]
queueattrs=sqs.get_queue_attributes(QueueUrl=queueurl)["Attributes"]
queuearn=queueattrs["QueueArn"]
pattern={"detail": detail["pattern"]}
events.put_rule(Name="my-rule",
State="ENABLED",
EventPattern=json.dumps(pattern))
events.put_targets(Rule="my-rule",
Targets=[{"Id": "my-target-id",
"Arn": queuearn}])
event=copy.deepcopy(eventbase)
event["Detail"]=json.dumps(detail["event"])
events.put_events(Entries=[event])
return drain_sqs(sqs, queue["QueueUrl"])
if __name__=="__main__":
try:
for detail in [{"event": {"root": "child"},
"pattern": {"root": ["child"]}},
{"event": {"root": ["child"]},
"pattern": {"root": ["child"]}}]:
messages=test_event_pattern(detail)
print ("%s -> %s" % (json.dumps(detail["event"]),
bool(len(messages))))
except ClientError as error:
print ("Error: %s" % str(error))

Related

Telegraf splits input data into different outputs

I want to write Telegraf config file which will:
Uses openweathermap input or custom http request result
{
"fields": {
...
"humidity": 97,
"temperature": -11.34,
...
},
"name": "weather",
"tags": {...},
"timestamp": 1675786146
}
Splits result on two similar JSONs:
{
"sensorID": "owm",
"timestamp": 1675786146,
"value": 97,
"type": "humidity"
}
and
{
"sensorID": "owm",
"timestamp": 1675786146,
"value": -11.34,
"type": "temperature"
}
Sends this JSONs into MQTT queue
Is it possible or I must create two different configs and make two api calls?
I found next configuration which solves my problem:
[[outputs.mqtt]]
servers = ["${MQTT_URL}", ]
topic_prefix = "owm/data"
data_format = "json"
json_transformation = '{"sensorID":"owm","type":"temperature","value":fields.main_temp,"timestamp":timestamp}'
[[outputs.mqtt]]
servers = ["${MQTT_URL}", ]
topic_prefix = "owm/data"
data_format = "json"
json_transformation = '{"sensorID":"owm","type":"humidity","value":fields.main_humidity,"timestamp":timestamp}'
[[inputs.http]]
urls = [
"https://api.openweathermap.org/data/2.5/weather?lat={$LAT}&lon={$LON}2&appid=${API_KEY}&units=metric"
]
data_format = "json"
Here we:
Retrieve data from OWM in input plugin.
Transform received data structure in needed structure in two different output plugins. We use this language https://jsonata.org/ for this aim.

special character conversation in bash output

Hi :P I'm a beginner here and i was doing a small project in bash to automatically create prewritten text files when at the last moment I realized that characters like "" (example: "format_version" goes out format_version)were deleted when writing output to my file. Please help me ('-')
python ID_1.py
python ID_2.py
echo "bash(...)"
ID1=$(cat link1.txt)
ID2=$(cat link2.txt)
echo "Name of your pack=$NP"
read NP
echo "This description=$DC"
read DC
cd storage/downloads
echo "{
("format_version"): 1,
"header": {
"name": "$NP",
"description": "$DC",
"uuid": "$ID1",
"version": [0, 0, 1]
},
"modules": [
{
"type": "resources",
"uuid": "$ID2",
"version": [0, 0, 1]
}
]
}" > manisfest.json

Need to print certain letters after a particular word using shell script

I am new to shell scripting and I want to print the IPs inside current cidr range and proposed cidr range below is the output
{
"acknowledgeRequiredBy": xxxxxx000,
"acknowledged": false,
"acknowledgedBy": "name#email.com",
"acknowledgedOn": xxxxxx00000,
"contacts": [
"dl#email.com",
"dl2#gmail.com"
],
"currentCidrs": [
"1.2.3.4/24",
"5.6.7.8/24",
"9.10.11.12/24",
"13.14.15.16/24",
"17.18.19.20/24",
"21.22.23.24/24",
"25.26.27.28/24",
],
"id": 1x4x3xx,
"latestTicketId": 0000,
"mapAlias": "sample name",
"mcmMapRuleId": 111xxx,
"proposedCidrs": [
"25.26.27.28/24",
"1.2.3.4/24",
"5.6.7.8/24",
"9.10.11.12/24",
],
"ruleName": "namerule.com",
"service": "S",
"shared": na,
"sureRouteName": "example",
I want the output as only the IPs please help me with the logic

OPA/Rego execute function for each element of an array

I am new at OPA/Rego and I am trying to write a policy to check if an Azure Network Security Group contains all the rules that I define on an array
package sample
default compliant = false
toSet(arr) = {x | x := arr[_]}
checkProperty(rule, index, propertySingular, propertyPlural) = true
{
object.get(input.properties.securityRules[index].properties, propertySingular, "") == object.get(rule, propertySingular, "")
count(toSet(object.get(input.properties.securityRules[index].properties, propertyPlural, [])) - toSet(object.get(rule, propertyPlural, []))) == 0
}
existRule(rule) = true
{
input.properties.securityRules[i].name == rule.name
input.properties.securityRules[i].properties.provisioningState == rule.provisioningState
input.properties.securityRules[i].properties.description == rule.description
input.properties.securityRules[i].properties.protocol == rule.protocol
checkProperty(rule, i, "sourcePortRange", "sourcePortRanges")
checkProperty(rule, i, "destinationPortRange", "destinationPortRanges")
checkProperty(rule, i, "sourceAddressPrefix", "sourceAddressPrefixes")
checkProperty(rule, i, "destinationAddressPrefix", "destinationAddressPrefixes")
input.properties.securityRules[i].properties.access == rule.access
input.properties.securityRules[i].properties.priority == rule.priority
input.properties.securityRules[i].properties.direction == rule.direction
}
compliant
{
rules := [
{
"name": "name1",
"provisioningState": "Succeeded",
"description": "description1",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "53",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Inbound",
"sourceAddressPrefixes":
[
"xx.xx.xx.xx",
"xx.xx.xx.xx",
"xx.xx.xx.xx"
],
},
{
"name": "name2",
"provisioningState": "Succeeded",
"description": "description2",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "54",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 2,
"direction": "Outbound",
"destinationAddressPrefixes":
[
"xx.xx.xx.xx",
"xx.xx.xx.xx",
"xx.xx.xx.xx"
]
}
]
#checks
existRule(rules[i])
}
The issue seem to be that when execute existRule(rules[i]) if one of the rules match it returns true, don't mather if other rules doesn't
If I replace existRule(rules[i]) with existRule(rules[0]) or existRule(rules[1]), it return true or false depending on if the rule on that position matchs.
Is there any way to get the result of the execution of existRule(rules[i]) for all the elements of the array?
I already tried result := [existRule(rules[i])] but it only return one element with true
Sure! Use a list comprehension and call the function inside of it, then compare the size of the result to what you had before. Given your example, you would replace existRule(rules[i]) with something like this:
compliantRules := [rule | rule := rules[_]
existRule(rule)]
count(compliantRules) == count(rules)

download files from artifactory from a subpath of the specified pattern

I'm trying to have my Jenkins job download some files from Artifactory:
a/b/c
d1
file1
d2
file2
This is what I want to achieve:
x/y/z
d1
file1
d2
file2
and I have the following file spec:
{
"files": [{
"pattern": "a/b/c/*",
"target": "x/y/z/",
"flat": "false",
"recursive": "true",
}]
}
but what I end up with instead is
x/y/z/a/b/c
d1
file1
d2
file2
What am I doing wrong?
You should use the following pattern
{
"files": [
{
"pattern": "a/b/c/(*)",
"target": "x/y/z/{1}",
"flat": "true",
"recursive": "true",
"regexp": "true"
}
]
}
By setting flat to true artifacts are downloaded to the exact target path specified and their hierarchy in the source repository is ignored.

Resources