Deploy telegram with webhook - telegram-bot

I'm more than a day look how to deploy telegram bot with webhook instead of polling..
even in the official doc it's not work for me https://github.com/python-telegram-bot/python-telegram-bot/wiki/Webhooks
someone can explain me oh give me some link to work tutorial how to deploy the most basic bot like this one
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
def start(update, context):
"""Send a message when the command /start is issued."""
update.message.reply_text('Hi!')
def help_command(update, context):
"""Send a message when the command /help is issued."""
update.message.reply_text('Help!')
def echo(update, context):
"""Echo the user message."""
update.message.reply_text(update.message.text)
def main():
TOKEN = "telegramToken"
updater = Updater(TOKEN, use_context=True)
# Get the dispatcher to register handlers
dp = updater.dispatcher
# on different commands - answer in Telegram
dp.add_handler(CommandHandler("start", start))
dp.add_handler(CommandHandler("help", help_command))
dp.add_handler(MessageHandler(Filters.text & ~Filters.command, echo))
PORT = int(os.environ.get('PORT', '5000'))
SERVER = 'myipserver/'
CERT = 'cert.pem'
updater.bot.setWebhook(SERVER + TOKEN, certificate=open(CERT, 'rb'))
# updater.bot.setWebhook(SERVER + TOKEN) also dont working
updater.start_webhook(listen="0.0.0.0", port=PORT, url_path=TOKEN)
# updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()

The problem is that the default port in App Engine is 8080
And the webhook in telegram does not support this port (just ports 443, 80, 88, or 8443)
https://core.telegram.org/bots/webhooks

I run my Telegram BOTs on Heroku and normally start the webhook then is set it:
updater.start_webhook(listen="0.0.0.0",
port=int(os.environ.get("PORT", 5000)),
url_path='token'
updater.bot.setWebhook("https://myapp.com/token")
updater.idle()
When deploying on Heroku you get a URL for your application using SSL (https://myapp.herokuapp.com), which you then configure via the BotFather.
Providing the BotFather with a HTTPS url is a must, I wonder if you don't do that or maybe there is an issue with the SSL certificate you are using (self-signed?)

Related

Connecting to redis through dash-extensions Websocket

Is there a way to listen to redis publisher message, through Websocket of dash-extensions package?
from dash_extensions import WebSocket
...
html.Div(id="message", className='p-4 border'),
WebSocket(url='ws://127.0.0.1:6379/1', id='ws')
This gives error in redis-server
# Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted.
Is such provision limited to specified redis clients only?
I believe that you are missing a component that reads the appropriate data from the Redis server and passes them through the websocket. This could be done in many different ways. Here is a small self-contained example written purely in Python,
import redis
import dash_html_components as html
from gevent import sleep
from dash import Dash
from dash.dependencies import Input, Output
from dash_extensions import WebSocket
from dash_extensions.websockets import SocketPool, run_server
# Read data from Redis and pass it through the web socket.
def ws_handler(ws):
while True:
sleep(2) # delay between updates, here 1s
value = redis.Redis().get('foo').decode("utf-8") # get redis value
ws.send(f"Redis value is [{value}]") # send data
# Inject some dummy data into Redis.
redis.Redis().set('foo', 'bar')
# Create example app.
app = Dash(prevent_initial_callbacks=True)
socket_pool = SocketPool(app, handler=ws_handler)
app.layout = html.Div([html.Div("Listening for message", id="log"), WebSocket(id="ws")])
#app.callback(Output("log", "children"), [Input("ws", "message")])
def update_graph(msg):
return msg['data']
if __name__ == '__main__':
run_server(app, port=5000) # 5000 if the default port

OIDC SSO in flask SSL certificate verify failed

I have one flask powered app, I'm trying to enable OIDC SSO for this app. I opted for wso2 as the identity server. I have created a callback URL and added the needful things in both the Identity Server and the flask app as shown below. The app is able to flow through the credential logging page and after that, I'm getting an SSL certificate verification error.
My try:
I have tried by using self signed certificates and app.run(ssl_context='adhoc') didn't worked.
Code Snippet:
from flask import Flask, g
from flask_oidc import OpenIDConnect
# import ssl
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__)
app.config.update({
'SECRET_KEY': 'SomethingNotEntirelySecret',
'TESTING': True,
'DEBUG': True,
'OIDC_CLIENT_SECRETS': 'client_secrets.json',
'OIDC_ID_TOKEN_COOKIE_SECURE': False,
'OIDC_REQUIRE_VERIFIED_EMAIL': False,
})
oidc = OpenIDConnect(app)
#app.route('/private')
#oidc.require_login
def hello_me():
# import pdb;pdb.set_trace()
info = oidc.user_getinfo(['email', 'openid_id'])
return ('Hello, %s (%s)! Return' %
(info.get('email'), info.get('openid_id')))
if __name__ == '__main__':
# app.run(host='sanudev', debug=True)
# app.run(debug=True)
# app.run(ssl_context='adhoc')
app.run(ssl_context=('cert.pem', 'key.pem'))
# app.run(ssl_context=('cert.pem', 'key.pem'))
Client Info:
{
"web": {
"auth_uri": "https://localhost:9443/oauth2/authorize",
"client_id": "hXCcX_N75aIygBIY7IwnWRtRpGwa",
"client_secret": "8uMLQ92Pm8_dPEjmGSoGF7Y6fn8a",
"redirect_uris": [
"https://sanudev:5000/oidc_callback"
],
"userinfo_uri": "https://localhost:9443/oauth2/userinfo",
"token_uri": "https://localhost:9443/oauth2/token",
"token_introspection_uri": "https://localhost:9443/oauth2/introspect"
}
}
App Info:
python 3.8
Flask 1.1.2
Hi Answering my own question just to reach the community effectively, here I can express where did I stuck and all the stories behind the fix.
TLDR:
The SSL issue was appearing because in OIDC flow wso2 server has to communicate or transfer secure-auth token only through the SSL tunnel. This is a mandatory standard need to keep for security purposes.
Yes carbon server has SSL certificate (self signed one) to make the secure token transfer through SSL Tunnel client also has to make at least self-signed certificate configuration.
Since I was using the flask-oidc library there is a provision to allow that, please refer to the configuration here.
{
"web": {
"auth_uri": "https://localhost:9443/oauth2/authorize",
"client_id": "someid",
"client_secret": "somesecret",
"redirect_uris": [
"https://localhost:5000/oidc_callback"
],
"userinfo_uri": "http://localhost:9763/oauth2/userinfo",
"token_uri": "http://localhost:9763/oauth2/token",
"token_introspection_uri": "http://localhost:9763/oauth2/introspect",
"issuer": "https://localhost:9443/oauth2/token" # This can solve your issue
}
}
For quick development purpose you can enable Secure connection in HTTPS by adding ad-hoc config in flask app run settings.
if __name__ == '__main__':
# app.run(ssl_context=('cert.pem', 'key.pem')) # for self signed cert
app.run(debug=True, ssl_context='adhoc') # Adhoc way of making https
Let me preface this answer with this one Caveat:
DO NOT DO THIS IN PRODUCTION ENVIRONMENTS
No, serously, do not do this in production, this should only be done for development purposes.
Anyways, open the oauth2client\transport.py file.
You're going to see this file location in your error that is spit out. for me it was in my anaconda env
AppData\Local\Continuum\anaconda3\envs\conda_env\lib\site-packages\oauth2client\transport.py
Find this line (line 73 for me)
def get_http_object(*args, **kwargs):
"""Return a new HTTP object.
Args:
*args: tuple, The positional arguments to be passed when
contructing a new HTTP object.
**kwargs: dict, The keyword arguments to be passed when
contructing a new HTTP object.
Returns:
httplib2.Http, an HTTP object.
"""
return httplib2.Http(*args, **kwargs)
change the return to
return httplib2.Http(*args, **kwargs, disable_ssl_certificate_validation=True)
You may need to do the same thing to line 445 of flask_oidc/__init__.py
credentials.refresh(httplib2.Http(disable_ssl_certificate_validation=True))
Upgrading certifi package should solve the problem.
pip install --upgrade certifi
It worked for me when I faced the exactly the same issue.

Unable to access unsecured https with selenium using browsermob proxy

I'm trying to embed browsermob proxy with my selenium (chrome) framework for UI automated testing in order to intercept responses and other networking.
Description :
Selenium webdriver using browsermob proxy and it works just fine - HTTP and secured HTTPS URL's are OK. When I'm trying to navigate to unsecured HTTPS URL I get this chrome error:
ERR_TUNNEL_CONNECTION_FAILED
Here's my python code:
class Browser(object):
display = None
browser = None
def __init__(self, implicitly_wait_seconds=10, is_visible=True, display_size=None, browser_name='chrome'):
if not is_visible:
self.display = Display(display_size)
self.server = Server('/home/erez/Downloads/browsermob-proxy-2.1.4/bin/browsermob-proxy')
self.server.start()
self.proxy = self.server.create_proxy()
self.capabilities = DesiredCapabilities.CHROME
self.proxy.add_to_capabilities(self.capabilities)
self.proxy.new_har("test", options={'captureHeaders': True, 'captureContent': True})
self.start_browser(display_size, implicitly_wait_seconds, browser_name)
def __enter__(self):
return self
def __exit__(self, _type, value, trace):
self.close()
def start_browser(self, display_size, implicitly_wait_seconds=10, browser_name='chrome'):
if browser_name == 'chrome':
chrome_options = Options()
# chrome_options.add_argument("--disable-extensions")
chrome_options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])
chrome_options.add_argument("--ssl-version-max")
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument('--proxy-server=%s' % self.proxy.proxy)
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--allow-insecure-localhost')
chrome_options.add_argument('--ignore-urlfetcher-cert-requests')
self.browser = webdriver.Chrome(os.path.dirname(os.path.realpath(__file__)) + "/chromedriver",
chrome_options=chrome_options, desired_capabilities=self.capabilities)
self.browser.implicitly_wait(implicitly_wait_seconds)
You can also call create_proxy with trustAllServers as argument:
self.proxy = self.server.create_proxy(params={'trustAllServers':'true'})
I faced the same problem for SSL proxying using BrowserMob Proxy. For this you have to install a certificate in your browser that has been defined in this link
Go to the bottom of the document, and you will see a section called "SSL support". Install the ca-certificate-rsa.cer in your browser and there would be no issue in SSL proxying anymore.
If installing Browsermobs/test servers certificates won't do the job, like in my case, not the most elegant way, but gets the job done:
You are able to bypass ERR_TUNNEL_CONNECTION_FAILED error by passing a trustAllServers-parameter to the proxy instance, which will disable the certificate verification for upstream servers. Unfortunately, for as far as I know, this functionality has not been implemented in the Browsermobs Python wrapper.
However, you can start the proxy with the parameter via Browsermobs REST API (see section REST API # https://github.com/lightbody/browsermob-proxy/blob/master/README.md). In case of Python, Requests might be the way to go.
Here's a snippet:
import json
import requests
from browsermobproxy import Server
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Start the proxy via python
server = Server('/path_to/bin/browsermob-proxy')
server.start()
# Start proxy instance with trustAllServers set to true, store returned port number
r = requests.post('http://localhost:8080/proxy', data = {'trustAllServers':'true'})
port = json.loads(r.text)['port']
# Start Chromedriver, pass on the proxy
chrome_options = Options()
chrome_options.add_argument('--proxy-server=localhost:%s' % port)
driver = webdriver.Chrome('/path_to/selenium/chromedriver', chrome_options=chrome_options)
# Get a site with untrusted cert
driver.get('https://site_with_untrusted_cert')
Also, if you need to access HAR-data, you'll need to do that also trough the REST API:
requests.put('http://localhost:8080/proxy/%s/har' % port, data = {'captureContent':'true'})
r = requests.get('http://localhost:8080/proxy/%s/har' % port)
Of course, since you're disabling safety features, this parameter should be used for limited testing purposes only.
Try use this
self.capabilities['acceptSslCerts'] = True

how to force close a client connection rabbitmq

I have a client server application that uses rabbitmq broker.
Client connects to rabbitmq and send messages to server. At some point if server decides that this client should not be connected to rabbitmq i want to be able to force disconnect client from rabbitmq border.
Note that in my case I don't want to send message to client to disconnect, on server side I want to just force disconnect this client from rabbitmq.
Couldn't find api to do this. Any help is appriciated.
You can use the management console plug-in in two ways:
Manually, going to the connection and "force close".
Through the HTTP API using "delete" /api/connections/name, here an python example:
import urllib2, base64
def calljsonAPI(rabbitmqhost, api):
request = urllib2.Request("http://" + rabbitmqhost + ":15672/api/" + api);
base64string = base64.encodestring('%s:%s' % ('guest', 'guest')).replace('\n', '')
request.add_header("Authorization", "Basic %s" % base64string);
request.get_method = lambda: 'DELETE';
urllib2.urlopen(request);
if __name__ == '__main__':
RabbitmqHost = "localhost";
#here you should get the connection detail through the api,
calljsonAPI(RabbitmqHost, "connections/127.0.0.1%3A49258%20-%3E%20127.0.0.1%3A5672");
You can use rabbitmqctl for close/force-close connections:
rabbitmqctl close_connection <connectionpid> <explanation>
<connectionpid> is from:
rabbitmqctl list_connections
#or
rabbitmqctl list_consumers

How to handle https traffic using libmproxy?

I want to implement a proxy server that intercepts both http and https requests. I came across libmproxy (http://mitmproxy.org/doc/scripting/libmproxy.html) that it is SSL-capable. I start with this simplest proxy that just prints the headers of all requests and responses, and forwards them to clients and servers normally.
#!/usr/bin/env python
from libmproxy import controller, proxy
import os
class Master(controller.Master):
def __init__(self, server):
controller.Master.__init__(self, server)
self.stickyhosts = {}
def run(self):
try:
return controller.Master.run(self)
except KeyboardInterrupt:
self.shutdown()
def handle_request(self, msg):
print "handle request.................................................."
print msg.headers
msg.reply()
def handle_response(self, msg):
print "handle response................................................."
print msg.headers
msg.reply()
config = proxy.ProxyConfig(
cacert = os.path.expanduser("~/.mitmproxy/mitmproxy-ca.pem")
)
server = proxy.ProxyServer(config, 1234)
m = Master(server)
m.run()
Then I configure http and ssl proxy in firefox to 127.0.0.1 port 1234. http seems to work fine as I can see all the headers are printed out. However, when the browser sends https requests, the proxy server does not print anything at all, and the browser displays "the connect was interrupted" error.
Further investigation reveals that the https requests go though the proxy server but not controller.Master. I see that proxy.ProxyHandler.establish_ssl() is being called when there is an https request, but the request does not go though controller.Master.handle_request(). Despite that establish_ssl() is called, the browser does not seem to get any response back. I test this with https://www.google.com.
First, how can I make proxy.ProxyHandler works properly with https requests/responses? Second, how can I modify controller.Master so that it can intercept https requests? I'm also open to other tools that I can build a custom http/https proxy server on top of.
You need to install the mitmproxy CA in the browser you are testing with.
Please see details here ("Installing the mitmproxy CA" section):
http://mitmproxy.org/doc/ssl.html
This solved the problem for me.