Secure another web app using Flask - python

I have a web app Foo which is not secured, and I want to secure it using Flask, and more features will come also in this Flask app.
Foo is accessible via port 8081. Foo and this Flask web are in the same server.
Do I have to rewrite every end point in Foo as follows?
#app.route('/overview')
def foo_overview():
if check_token():
r = requests.get("http://localhost:8081/overview")
return r.content
else:
return redirect('/login')
or is there a convenient way to open a tunnel to localhost?
#app.route('/')
def foo_app():
if check_token():
# port 8081 now is opened for this connection
url = tunnel("http://localhost:8081")
return redirect(url)
else:
return redirect('/login')
My idea is to not open port 8081, but open 80, so users go from port 80 and if passing security check, they can start to use the service at 8081.

from flask import stream_with_context
#app.route('/<path:path>')
def foo_app(path):
if check_token():
# port 8081 now is opened for this connection
req = requests.get("http://localhost:8001/%s"%path, stream = True)
return Response(stream_with_context(req.iter_content()), content_type = req.headers['content-type'])
else:
return redirect('/login')
I borrowed most of this from http://flask.pocoo.org/snippets/118/

Related

Not printing to the console upon establishing connection to the server

I'm currently following a Udemy course that's having me use flask and socketio to use a neural network model to drive a simulated car. However, as he's explaining the basics of how flask and socketio work, he had us write this code:
import socketio
import eventlet
from flask import Flask
sio = socketio.Server()
app = Flask(__name__)
#sio.on('connect')
def connect(sid, environ):
print('Connected')
if __name__ == "__main__":
app = socketio.Middleware(sio, app)
eventlet.wsgi.server(eventlet.listen(('', 4567)), app)
Which is supposed to print "Connected!" to the console when we connect to the server. Now, I get this message when I run it, so I'm pretty sure I'm connected.
(7532) accepted ('127.0.0.1', 49374)
But it's refusing to print "Connected!" when I connect like it's supposed to, no matter what I try.
EDIT:
So, I'm still not sure what the root cause of this is, but I found out how to fix it.
conda install python-engineio==3.13.2
conda install python-socketio==4.6.1
You might need to run anaconda as an administrator. If so, search for "Anaconda Powershell Prompt" then run it as an admin.
socketio uses special protocol so you need special client to use it.
At least
import socketio
sio = socketio.Client()
con = sio.connect('http://0.0.0.0:4567')
sio.wait()
I will not work with web browser. With web browser you can see only accepted.
Browser have to load web page which uses special JavaScript module to use socketio.
You can find more details in socketio documentation: Client
EDIT:
And here server which you can test with web browser.
When you open http://0.0.0.0:4567 in browser then index() sends to browser HTML with JavaScript code which loads special library and uses socketio to send own event. And you should see Connected, my event. When you close page or browser then you should see Disconnected
It is based on example from documentation for flask-socketio
import socketio
import eventlet
from flask import Flask
sio = socketio.Server()
app = Flask(__name__)
#app.route('/')
def index():
return """
Hello World!
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on('connect', function() {
socket.emit('my event', {data: 'Im connected!'});
});
</script>
"""
#sio.on('connect')
def connect(sid, environ):
print('Connected')
#sio.on('disconnect')
def disconnect(sid): # without `environ`
print('Disconnected')
#sio.on('my event')
def my_event(sid, environ):
print('my event')
if __name__ == "__main__":
app = socketio.Middleware(sio, app)
eventlet.wsgi.server(eventlet.listen(('', 4567)), app)

Bot after deploing to server on debian doesn't work withou threaded (telebot, python)

i cache the problem, sense of this problem is bot, which doesn't work without arg threaded, anyone have a solution for this problem?
Server Linux Ubuntu 18.04 / centos 8 (both doesn't work) on first clear uwsgi on second uwsgi + nginx, and bot work with threaded, but without not.
I want achieve that my bot can work in threaded mode, i don't have errors and others, if i start my bot without parametr threaded (default it true)
bot = telebot.TeleBot('my_token')
The string which i demonstrate under (i mark it <----):
#app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_updates([update,]) # <---- THIS STRING
bot.send_message(update.message.from_user.id, update.message.text)
return ''
else:
flask.abort(403)
Doesn't work, and from this all of my other code doesn't work, because it's method let start the query to handle of all my others handlers, but this not happening because threaded is True, if i set this parametr in false it's work, but it's work not so good and I want so help to solve this problem.
I finded description(github forum) why it's not work, but my host VDSINA and i same have one thread, maybe it's a problem?
My uwsgi configuration:
[uwsgi]
socket = 127.0.0.1:9090
#shared-socket = :9090
#https = =0,webhook_cert.pem,webhook_pkey.pem
wsgi-file = foobar.py
callable = app
master = true
processes = 4
threads = 2
enable-threads = true
single-interpreter = true
But how I change this and how many time, I don't get the solve.
All code of my bot:
from flask import Flask
import flask
from time import sleep
import logging
import telebot
app = Flask(__name__)
#app.route('/')
def index():
print("simple output")
return "<span style='color:red'>I am app 1</span>"
bot = telebot.TeleBot('my_tok')
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
API_TOKEN = bot.token
WEBHOOK_HOST = 'ip_my_serve'
# nginx # WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
WEBHOOK_SSL_CERT = '/etc/ssl/certs/nginx-selfsigned.crt' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = '/etc/ssl/private/nginx-selfsigned.key' # Path to the ssl private key
WEBHOOK_URL_BASE = "https://%s" % (WEBHOOK_HOST)
WEBHOOK_URL_PATH = "/%s/" % (API_TOKEN)
bot.remove_webhook()
sleep(1)
bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
#app.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_updates([update,])
bot.send_message(update.message.from_user.id, update.message.text)
return ''
else:
flask.abort(403)
#bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
A solve for this answer it's change uwsgi on cherrypy, and it's my solution.

Using mitmproxy inside a Python script to connect to upstream proxy (with user & password)

I am trying to use mitmproxy behind a company proxy that requires a user/password login.
The setup is:
Local PC's browser -> mitmproxy (on local PC) -> company proxy -> internet.
Based on this SO thread, this is how you use mitmproxy within a Python program. This example works fine when there's no proxy.
from mitmproxy.options import Options
from mitmproxy.proxy.config import ProxyConfig
from mitmproxy.proxy.server import ProxyServer
from mitmproxy.tools.dump import DumpMaster
class Addon(object):
def __init__(self):
pass
def request(self, flow):
# examine request here
pass
def response(self, flow):
# examine response here
pass
if __name__ == "__main__":
options = Options(listen_host='0.0.0.0', listen_port=8080, http2=True)
m = DumpMaster(options, with_termlog=False, with_dumper=False)
config = ProxyConfig(options)
m.server = ProxyServer(config)
m.addons.add(Addon())
try:
print('starting mitmproxy')
m.run()
except KeyboardInterrupt:
m.shutdown()
Assuming the company proxy is at IP "1.2.3.4" port 3128 and requires a
login USER and PASSWORD, how can I change this script to have mitproxy
use that proxy instead of going to the internet directly?
Addition info: I am not using mitmdump with the script-parameter to run this script.
The goal is to run this from Python 3.8 with a pip-installed mitmproxy

how can I connect, from a flask app, to a remote elasticsearch cluster on aws?

I have an elasticsearch cluster running on an EC2 server. I get a variety of different error mesages when I try to connect.
Currently, in the elasticsearch.yml file all the transport items are commented out but I have tried:
network.host: 0.0.0.0
and
network.host: ec2-xx-xxx-xxx.aws.instance.com
In my flask app the code is as follows:
from datetime import datetime
from flask import Flask, jsonify, request
from elasticsearch import Elasticsearch
#es = Elasticsearch()http://34.245.51.240/
es = Elasticsearch(['ec2-34-xxx-xx-240.eu-west-1.compute.amazonaws.com','9200'])
#es = Elasticsearch(['34.245.51.240','9200'])
application = Flask(__name__)
#application.route('/', methods=['GET'])
def index():
#results = es.get(index='contents', doc_type='title', id='my-new-slug')
#return jsonify(results['_source'])
doc = {
'author': 'kimchy',
'text': 'Elasticsearch: cool. bonsai cool.',
'timestamp': datetime.now(),
}
res = es.index(index="test-index", doc_type='tweet', id=1, body=doc)
print(res['res'])
return res
#application.run(port=5000, debug=True)
if __name__ == '__main__':
application.debug = True
application.run()
I have googled multiple times and tried every possible configuration that I can find.
What is the correct way to achieve this?
Thank you.
I hope this will help other people.
elasticsearch defaults to Port 9200 so it is necessary to open such a Port on the EC2 server as such:
CustomTCP TCP 9200 0.0.0.0
This is done by editing the security group wizard that set up security groups when you set up the server.
Then in your Python application the connection string is:
es = Elasticsearch("http://00.111.222.33") //the public IP you can see on your EC2 dashboard
That's it. Hours of anguish and so simple.

Trouble Sending iOS push notifications from Google App Engine

I'm working on my first iOS app that uses push notifications. I have a python script that lets me to send push notifications from my machine but I'm unable to get this working with the Google App Engine Launcher.
When I run this on GAE I get nothing - no errors and no push notifications. What am I doing wrong? I know the code for sending the actual notification is working properly but I'm not able to duplicate this on Google's servers.
Here is the script I'm trying to run with GAE Launcher:
import os
import cgi
import webapp2
from google.appengine.ext.webapp.util import run_wsgi_app
import ssl
import json
import socket
import struct
import binascii
TOKEN = 'my_app_token'
PAYLOAD = {'aps': {'alert':'Push!','sound':'default'}}
class APNStest(webapp2.RequestHandler):
def send_push(token, payload):
# Your certificate file
cert = 'ck.pem'
# APNS development server
apns_address = ('gateway.sandbox.push.apple.com', 2195)
# Use a socket to connect to APNS over SSL
s = socket.socket()
sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, certfile=cert)
sock.connect(apns_address)
# Generate a notification packet
token = binascii.unhexlify(token)
fmt = '!cH32sH{0:d}s'.format(len(payload))
cmd = '\x00'
message = struct.pack(fmt, cmd, len(token), token, len(payload), payload)
sock.write(message)
sock.close()
send_push(TOKEN, json.dumps(PAYLOAD))
application = webapp2.WSGIApplication([
('/apns', APNStest)
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
So the solution was very simple as I expected. I had enabled billing for the project on cloud.google.com but needed to have billing enabled at appengine.google.com as well. Stupid mistake that set me back 2 days.

Categories

Resources