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 | |||