Connect to RabbitMQ instance remotely (created on AWS) - amazon-web-services

I'm having trouble connecting to a RabbitMQ instance (it's my first time doing so). I've spun one up on AWS, and been given access to an admin panel which I'm able to access.
I'm trying to connect to the RabbitMQ server in python/pika with the following code:
import pika
import logging
logging.basicConfig(level=logging.DEBUG)
credentials = pika.PlainCredentials('*******', '**********')
parameters = pika.ConnectionParameters(host='a-25c34e4d-a3eb-32de-abfg-l95d931afc72f.mq.us-west-1.amazonaws.com',
port=5671,
virtual_host='/',
credentials=credentials,
)
connection = pika.BlockingConnection(parameters)
I get pika.exceptions.IncompatibleProtocolError: StreamLostError: ("Stream connection lost: ConnectionResetError(54, 'Connection reset by peer')",) when I run the above.

you're trying to connect through AMQP protocol and AWS is using AMQPS, you should add ssl_options to your connection parameters like this
import ssl
logging.basicConfig(level=logging.DEBUG)
credentials = pika.PlainCredentials('*******', '**********')
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
parameters = pika.ConnectionParameters(host='a-25c34e4d-a3eb-32de-abfg-l95d931afc72f.mq.us-west-1.amazonaws.com',
port=5671,
virtual_host='/',
credentials=credentials,
ssl_options=pika.SSLOptions(context)
)
connection = pika.BlockingConnection(parameters)

Related

AWS SeS From Lambda (works with Python, not with .Net)

I have a .NET lambda that sends emails via SES. I have a VPCe for SeS coupled with all of the required port, subnet & ACL config.
I created a Python lambda to do exactly the same as my .NET Lambda. It's joined to the same subnets, same security group & uses the same SMTP user and password.
The Python code works fine, connects to SES and sends the emails without fail but my .NET Lambda doesn't.
The last thing in my logs is:
ConnectAsync is going to be called
When calling the uri/path it says "Service Unavailable, 500."
I know the code works as if it's in debug on my dev machine pointing at the www-ses endpoint, it works fine.
I've also tried Nat gateways as an alternative (same issue) but I've settled with VPCe as I know my Python lambda works fine.
.NET:
try
{
using var smtp = new SmtpClient();
LambdaLogger.Log($"smtp ConnectAsync is going to be called for host {Configuration["SmtpHost"]} and port {Configuration["SmtpPort"].To<int>()} ");
//await smtp.ConnectAsync(Configuration["SmtpHost"], Configuration["SmtpPort"].To<int>(), SecureSocketOptions.StartTlsWhenAvailable);
await smtp.ConnectAsync("vpce-0af6f6a54b8c6d652-ltbm2mcx.email-smtp.eu-west-2.vpce.amazonaws.com", 587, SecureSocketOptions.StartTlsWhenAvailable);
LambdaLogger.Log($"SMTP connection created on {Configuration["SmtpHost"]} and port {Configuration["SmtpPort"].To<int>()}.");
await smtp.AuthenticateAsync(Configuration["SESUserName"], Configuration["SESPassword"]);
LambdaLogger.Log($"User auth completed for user .");
await smtp.SendAsync(email);
LambdaLogger.Log("email sent.");
emailMessage.isDeleted = true;
_applicationContext.EmailMessages.Update(emailMessage);
smtp.Disconnect(true);
}
catch (Exception ex)
{
emailMessage.Retries = emailMessage.Retries++;
_applicationContext.EmailMessages.Update(emailMessage);
LambdaLogger.Log($"Email Sending Error: {ex.ToFullMessage()}");
}
await _applicationContext.SaveChangesAsync();
Python:
import json
import smtplib
from email.mime.text import MIMEText
def lambda_handler(event, context):
sender = '<removd>'
receivers = ['<removed>']
port = 587
msg = MIMEText('This is test mail')
msg['Subject'] = 'Test mail'
msg['From'] = '<removed>'
msg['To'] = '<remvoed>'
with smtplib.SMTP('vpce-0af6f6a54b8c6d652-ltbm2mcx.email-smtp.eu-west-2.vpce.amazonaws.com', 587) as server:
server.starttls()
server.login('<removed>', '<removed>')
server.sendmail(sender, receivers, msg.as_string())
print("Successfully sent email")

Extract connections in airflow and use in boto3

I am. trying to extract connections from airflow as
key,pass = BaseHook.get_connection('aws_default')
print(conn.get_extra())
and use it in my boto3 connection as:
account_id = boto3.client('sts',aws_access_key_id=key,
aws_secret_access_key=pass).get_caller_identity().get('Account').
I am getting this error, how to resolve this?
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: connection

Call MSSQL with Windows Auth from AWS Lambda

Is it possible to call MSSQL from AWS Lambda when MSSQL is part of windows domain and only allows windows authentication?
E.g. Is there any way to run Lambda function under AD user?
or use AD connector to associate AD user with IAM account and run Lambda under that account?
Yes, we can use pymssql python module inside the lambda function to connect to mssql server and execute your commands. You need to zip the pymssql module as a lambda deployment package.
here is the example of command and connection:
import boto3
import pymssql
#setup connection
conn = pymssql.connect("serverurl", "username", "password", "dbname")
#setup cursor, so that you can use it to execute your commands
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE persons (
id INT NOT NULL,
name VARCHAR(100),
salesrep VARCHAR(100),
PRIMARY KEY(id)""")
# you must call commit() to persist your data if you don't set autocommit to True
conn.commit()
But, to connect using Windows Authentication, here is some mods:
When connecting using Windows Authentication, this is how to combine the database’s hostname and instance name, and the Active Directory/Windows Domain name and the username.
conn = pymssql.connect(
host=r'dbhostname\myinstance',
user=r'companydomain\username',
password=PASSWORD,
database='DatabaseOfInterest'
)

Why is my lambda not able to talk to elasticache?

I have an Redis ElastiCache cluster that has a FQDN for the primary node in the format: master.clustername.x.euw1.cache.amazonaws.com. I also have a Route53 record with the CNAME pointing at that FQDN.
I have a .net core lambda in the same VPC as the cluster, with access to the cluster via security groups. The lambda talks to the cluster using the Redis library developed by Stack Overflow (Github repo here for reference).
If I give the lambda the hostname the FQDN for the Redis cluster (the one that starts with master) I can connect, save data and read it.
If I give the lambda the CNAME (and that CNAME gives the same IP address as the FQDN when I ping it from my local machine and also if I use Dns.GetHostEntry within the lambda) it doesn't connect and I get the following error message:
One or more errors occurred. (It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. SocketFailure on PING): AggregateException
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at lambda_method(Closure , Stream , Stream , LambdaContextInternal )
at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(Func`1 multiplexerFactory, TextWriter log) in c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs:line 890
at lambda.Redis.RedisClientBuilder.Build(String redisHost, String redisPort, Int32 redisDbId) in C:\BuildAgent\work\91d24911506461d0\src\Lambda\Redis\RedisClientBuilder.cs:line 9
at lambda.Ioc.ServiceBuilder.GetRedisClient() in C:\BuildAgent\work\91d24911506461d0\src\Lambda\IoC\ServiceBuilder.cs:line 18
at lambda.Ioc.ServiceBuilder.GetServices() in C:\BuildAgent\work\91d24911506461d0\src\Lambda\IoC\ServiceBuilder.cs:line 11
at Handlers.OrderHandler.Run(SNSEvent request, ILambdaContext context) in C:\BuildAgent\work\91d24911506461d0\src\Lambda\Handlers\OrderHandler.cs:line 26
Has anyone seen anything similar to this?
It turned out that because I was using an SSL certificate on the elasticache cluster and the SSL certificate was bound the the master. endpoint whereas I was trying to connect to the CNAME, the certificate validation was failing.
So I ended up querying the Route53 record within the code to get the master endpoint and it worked.
Possible workaround to isolate problems from your client lib -- follow AWS' tutorial and rewrite your Lambda to something like the code below (example in Python).
from __future__ import print_function
import time
import uuid
import sys
import socket
import elasticache_auto_discovery
from pymemcache.client.hash import HashClient
#elasticache settings
elasticache_config_endpoint = "your-elasticache-cluster-endpoint:port"
nodes = elasticache_auto_discovery.discover(elasticache_config_endpoint)
nodes = map(lambda x: (x[1], int(x[2])), nodes)
memcache_client = HashClient(nodes)
def handler(event, context):
"""
This function puts into memcache and get from it.
Memcache is hosted using elasticache
"""
#Create a random UUID... this will the sample element we add to the cache.
uuid_inserted = uuid.uuid4().hex
#Put the UUID to the cache.
memcache_client.set('uuid', uuid_inserted)
#Get item (UUID) from the cache.
uuid_obtained = memcache_client.get('uuid')
if uuid_obtained.decode("utf-8") == uuid_inserted:
# this print should go to the CloudWatch Logs and Lambda console.
print ("Success: Fetched value %s from memcache" %(uuid_inserted))
else:
raise Exception("Value is not the same as we put :(. Expected %s got %s" %(uuid_inserted, uuid_obtained))
return "Fetched value from memcache: " + uuid_obtained.decode("utf-8")
Reference: https://docs.aws.amazon.com/lambda/latest/dg/vpc-ec-deployment-pkg.html

How to establish authorized request with keystone using python-openstack client API v3

I have problems with python-openstackclient library.When i run this code to authorize with keystone:
from keystoneclient import session
from keystoneclient.v3 import client
from keystoneclient.auth.identity import v3
password = v3.PasswordMethod(username='idm',password='idm',user_domain_name='idm')
auth = v3.Auth(auth_url='http://127.0.0.1:5000/v3',auth_methods=[password],project_id='idm')
sess = session.Session(auth=auth)
keystone = client.Client(session=sess)
keystone.users.list()
Im getting this error:
keystoneclient.openstack.common.apiclient.exceptions.Unauthorized: The request you have made requires authentication. (HTTP 401)
But when i try openstack client program:
openstack user list
It gives me good output.
I have next global variables in my .bashrc:
export OS_SERVICE_ENDPOINT=http://127.0.0.1:35357/v3
export OS_AUTH_URL=http://127.0.0.1:5000/v3
export OS_TENANT_NAME=idm
export OS_USERNAME=idm
export OS_PASSWORD=idm
export OS_IDENTITY_API_VERSION=3
export OS_URL=http://127.0.0.1:35357/v3
What could be the problem with that python code?
Thanks!
I had the same problem but after applying proposed solution I was getting :
keystoneauth1.exceptions.connection.ConnectFailure: Unable to
establish connection to http://192.0.2.12:35357/v2.0/users:
HTTPConnectionPool(host='192.0.2.12', port=35357): Max retries
exceeded with url: /v2.0/users (Caused by
NewConnectionError(': Failed to establish a new connection:
[Errno 110] Connection timed out',))
Note that my auth_url='https://myopenstack.somewhere.org:13000/v3',
It turns out that the client was discovering and using services on a interface which by default is 'Admin', and is unreachable for me. When forcing the interface to Public it works :
keystone = client.Client(session=sess, interface='Public')
I managed to do it like this:
from keystoneclient import session
from keystoneclient.v3 import client
from keystoneclient.auth.identity import v3
auth = v3.Password(auth_url='http://127.0.0.1:5000/v3',user_id='idm',password='idm',project_id='2545070293684905b9623095768b019d')
sess = session.Session(auth=auth)
keystone = client.Client(session=sess)
keystone.users.list()