Logs in the second network are collected by a logstash instance and forwarded over the bridge to another logstash instance, which prints them.master
| @@ -0,0 +1,55 @@ | |||||
| version: '3.9' | |||||
| services: | |||||
| high-logstash: | |||||
| image: opensearchproject/logstash-oss-with-opensearch-output-plugin:latest | |||||
| command: logstash -f /pipeline.conf | |||||
| volumes: | |||||
| - "./pipelines/rabbitmq-stdout.conf:/pipeline.conf:ro" | |||||
| networks: | |||||
| - high | |||||
| depends_on: | |||||
| - high-transfer | |||||
| high-transfer: | |||||
| image: rabbitmq:latest | |||||
| volumes: | |||||
| - "./rabbitmq/load-definitions.conf:/etc/rabbitmq/conf.d/20-load-definitions.conf:ro" | |||||
| - "./rabbitmq/high-definitions.json:/etc/rabbitmq/definitions.json:ro" | |||||
| networks: | |||||
| - transfer | |||||
| - high | |||||
| low-transfer: | |||||
| image: rabbitmq:latest | |||||
| volumes: | |||||
| - "./rabbitmq/load-definitions.conf:/etc/rabbitmq/conf.d/20-load-definitions.conf:ro" | |||||
| - "./rabbitmq/low-definitions.json:/etc/rabbitmq/definitions.json:ro" | |||||
| - "./rabbitmq/low-plugins:/etc/rabbitmq/enabled_plugins:ro" | |||||
| networks: | |||||
| - transfer | |||||
| - low | |||||
| depends_on: | |||||
| - high-transfer | |||||
| low-logstash: | |||||
| image: opensearchproject/logstash-oss-with-opensearch-output-plugin:latest | |||||
| command: logstash -f /pipeline.conf | |||||
| volumes: | |||||
| - "./pipelines/snmptrap-rabbitmq.conf:/pipeline.conf:ro" | |||||
| networks: | |||||
| - low | |||||
| depends_on: | |||||
| - low-transfer | |||||
| low-snmp-sender: | |||||
| build: snmp-sender | |||||
| networks: | |||||
| - low | |||||
| depends_on: | |||||
| - low-logstash | |||||
| networks: | |||||
| high: | |||||
| transfer: | |||||
| low: | |||||
| @@ -0,0 +1,13 @@ | |||||
| input { | |||||
| rabbitmq { | |||||
| host => "high-transfer" | |||||
| queue => "to-logstash" | |||||
| user => "logstash" | |||||
| password => "logstash" | |||||
| durable => true | |||||
| } | |||||
| } | |||||
| output { | |||||
| stdout {} | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| input { | |||||
| snmptrap { | |||||
| community => "public" | |||||
| port => 162 | |||||
| } | |||||
| } | |||||
| output { | |||||
| rabbitmq { | |||||
| host => "low-transfer" | |||||
| exchange => "logstash" | |||||
| exchange_type => "fanout" | |||||
| user => "logstash" | |||||
| password => "logstash" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,13 @@ | |||||
| input { | |||||
| syslog {} | |||||
| } | |||||
| output { | |||||
| stdout {} | |||||
| rabbitmq { | |||||
| host => "low-transfer" | |||||
| exchange => "to-high" | |||||
| exchange_type => "direct" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,96 @@ | |||||
| { | |||||
| "bindings": [ | |||||
| { | |||||
| "vhost": "/", | |||||
| "source": "from-low", | |||||
| "destination": "to-logstash", | |||||
| "destination_type": "queue", | |||||
| "routing_key": "", | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "exchanges": [ | |||||
| { | |||||
| "name": "from-low", | |||||
| "vhost": "/", | |||||
| "type": "fanout", | |||||
| "durable": true, | |||||
| "auto_delete": false, | |||||
| "internal": false, | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "global_parameters": [], | |||||
| "parameters": [], | |||||
| "permissions": [ | |||||
| { | |||||
| "configure": ".*", | |||||
| "read": ".*", | |||||
| "user": "guest", | |||||
| "vhost": "/", | |||||
| "write": ".*" | |||||
| }, | |||||
| { | |||||
| "configure": "^to-logstash$", | |||||
| "read": "^to-logstash$", | |||||
| "user": "logstash", | |||||
| "vhost": "/", | |||||
| "write": "^$" | |||||
| }, | |||||
| { | |||||
| "configure": "^$", | |||||
| "read": "^$", | |||||
| "write": "^from-low$", | |||||
| "user": "shovel", | |||||
| "vhost": "/" | |||||
| } | |||||
| ], | |||||
| "policies": [], | |||||
| "queues": [ | |||||
| { | |||||
| "name": "to-logstash", | |||||
| "vhost": "/", | |||||
| "durable": true, | |||||
| "auto_delete": false, | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "rabbit_version": "3.11.0", | |||||
| "rabbitmq_version": "3.11.0", | |||||
| "topic_permissions": [], | |||||
| "users": [ | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "logstash", | |||||
| "password_hash": "4U3iLR6025zaf1loUjUYZBqAqczafRLf5cTVy5jnSF1F1deW", | |||||
| "tags": [] | |||||
| }, | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "shovel", | |||||
| "password_hash": "Rd+zj6GaVUkJPevYVMYYrfPYRReUnYxtlsyDtvQN29VNK2va", | |||||
| "tags": [] | |||||
| }, | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "guest", | |||||
| "password_hash": "jr8pwUpOa/7R8s/DWI7lYIH7H21e5UhBFjGniiRxwyL4GvQ2", | |||||
| "tags": [ | |||||
| "administrator" | |||||
| ] | |||||
| } | |||||
| ], | |||||
| "vhosts": [ | |||||
| { | |||||
| "limits": [], | |||||
| "metadata": { | |||||
| "description": "Default virtual host", | |||||
| "tags": [] | |||||
| }, | |||||
| "name": "/" | |||||
| } | |||||
| ] | |||||
| } | |||||
| @@ -0,0 +1,3 @@ | |||||
| definitions.skip_if_unchanged = true | |||||
| definitions.import_backend = local_filesystem | |||||
| definitions.local.path = /etc/rabbitmq/definitions.json | |||||
| @@ -0,0 +1,110 @@ | |||||
| { | |||||
| "bindings": [ | |||||
| { | |||||
| "vhost": "/", | |||||
| "source": "logstash", | |||||
| "destination": "to-high", | |||||
| "destination_type": "queue", | |||||
| "routing_key": "", | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "exchanges": [ | |||||
| { | |||||
| "name": "logstash", | |||||
| "vhost": "/", | |||||
| "type": "fanout", | |||||
| "durable": true, | |||||
| "auto_delete": false, | |||||
| "internal": false, | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "global_parameters": [], | |||||
| "parameters": [ | |||||
| { | |||||
| "value": { | |||||
| "src-uri": "amqp://shovel:shovel@localhost", | |||||
| "src-queue": "to-high", | |||||
| "dest-uri": "amqp://shovel:shovel@high-transfer", | |||||
| "dest-exchange": "from-low", | |||||
| "ack-mode": "on-confirm", | |||||
| "delete-after": "never" | |||||
| }, | |||||
| "vhost": "/", | |||||
| "component": "shovel", | |||||
| "name": "shovel-low-high" | |||||
| } | |||||
| ], | |||||
| "permissions": [ | |||||
| { | |||||
| "configure": ".*", | |||||
| "read": ".*", | |||||
| "user": "guest", | |||||
| "vhost": "/", | |||||
| "write": ".*" | |||||
| }, | |||||
| { | |||||
| "configure": "^logstash$", | |||||
| "read": "^$", | |||||
| "user": "logstash", | |||||
| "vhost": "/", | |||||
| "write": "^logstash$" | |||||
| }, | |||||
| { | |||||
| "configure": "^$", | |||||
| "read": "^to-high$", | |||||
| "write": "^$", | |||||
| "user": "shovel", | |||||
| "vhost": "/" | |||||
| } | |||||
| ], | |||||
| "policies": [], | |||||
| "queues": [ | |||||
| { | |||||
| "name": "to-high", | |||||
| "vhost": "/", | |||||
| "durable": true, | |||||
| "auto_delete": false, | |||||
| "arguments": {} | |||||
| } | |||||
| ], | |||||
| "rabbit_version": "3.11.0", | |||||
| "rabbitmq_version": "3.11.0", | |||||
| "topic_permissions": [], | |||||
| "users": [ | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "logstash", | |||||
| "password_hash": "xgcwpKociAT+8XH28TN8kSGyJCzdRQ7yGx07EC59uqVJDGRo", | |||||
| "tags": [] | |||||
| }, | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "shovel", | |||||
| "password_hash": "lVd8P66d7wg2DI88eFbIFry2C6uoHciL5GhacyR2LLd7YrSM", | |||||
| "tags": [] | |||||
| }, | |||||
| { | |||||
| "hashing_algorithm": "rabbit_password_hashing_sha256", | |||||
| "limits": {}, | |||||
| "name": "guest", | |||||
| "password_hash": "V+I16wJVwnhij+/3MW7AXFkSwh41KRRRewc1rT1I2x6HEIqU", | |||||
| "tags": [ | |||||
| "administrator" | |||||
| ] | |||||
| } | |||||
| ], | |||||
| "vhosts": [ | |||||
| { | |||||
| "limits": [], | |||||
| "metadata": { | |||||
| "description": "Default virtual host", | |||||
| "tags": [] | |||||
| }, | |||||
| "name": "/" | |||||
| } | |||||
| ] | |||||
| } | |||||
| @@ -0,0 +1 @@ | |||||
| [rabbitmq_management, rabbitmq_shovel]. | |||||
| @@ -0,0 +1,45 @@ | |||||
| #!/bin/python | |||||
| import os | |||||
| import argparse | |||||
| from hashlib import sha256 | |||||
| from base64 import b64encode, b64decode | |||||
| from binascii import hexlify | |||||
| def generate_hash(password, salt=None): | |||||
| if salt is None: | |||||
| salt = os.urandom(4) | |||||
| salted = salt + password.encode('utf-8') | |||||
| hashed = salt + sha256(salted).digest() | |||||
| return b64encode(hashed).decode('utf-8') | |||||
| def test_hash(hashed, password, expected_salt=None): | |||||
| hash_bytes = b64decode(hashed) | |||||
| salt = hash_bytes[0:4] | |||||
| if expected_salt is not None and salt != expected_salt: | |||||
| return f'Hash {hexlify(hash_bytes)} with salt {hexlify(salt)} does not match expected salt {hexlify(expected_salt)}' | |||||
| if generate_hash(password, salt) == hashed: | |||||
| return f'Password matches hash' | |||||
| else: | |||||
| return f'Password does not match hash' | |||||
| if __name__ == '__main__': | |||||
| parser = argparse.ArgumentParser(description='Tool for hashing user passwords that can be added in RabbitMQ config files.') | |||||
| parser.add_argument('password', type=str, help='The password to hash or test against') | |||||
| parser.add_argument('-s', '--salt', dest='salt', type=str, help='Use a given salt instead of generatinga random one. If used with the --test argument, it verifies that the hash used this salt') | |||||
| parser.add_argument('-t', '--test', metavar='HASH', dest='test', type=str, help='Instead of hashing a password, check if a password matches a hash') | |||||
| args = parser.parse_args() | |||||
| if args.salt: | |||||
| salt = bytes.fromhex(args.salt) | |||||
| else: | |||||
| salt = None | |||||
| if args.test: | |||||
| print(test_hash(args.test, args.password, salt)) | |||||
| else: | |||||
| print(generate_hash(args.password, salt)) | |||||
| @@ -0,0 +1,8 @@ | |||||
| FROM debian:latest | |||||
| RUN apt-get update | |||||
| RUN apt-get install --yes snmp | |||||
| COPY main.sh /main.sh | |||||
| CMD "/main.sh" | |||||
| @@ -0,0 +1,9 @@ | |||||
| #!/bin/sh | |||||
| while true; do | |||||
| echo "Sending trap" | |||||
| snmptrap -c public -v 2c low-logstash "" 1.3.6.1.2.1.1.5.0 | |||||
| sleep 1 | |||||
| done | |||||