I have two containers Auth and Frontend. I have managed to get both the containers working independently, I need to establish the link between the two to send and receive HTTP requests.
Generally, the connections are made in angular like http://localhost:3000/auth/.
Note: Both are in different deployments and services.
Should I be using Ingress or Nginx?
If your Frontend angular application, needs to connect to the Auth application an the two run on different networks, then just use the IP of your host running the Auth container. If your app requires load balancing, security or you just want to add another level of abstraction and control you may use a proxy like Nginx.
service will do the job, you just need to replace localhost with service name.
Related
We deployed our flask application to AWS lambda and would like to restrict to access to it to:
Our development team (some external IP for everyone)
Wordpress server (static IP)
Bitbucket (for automatic deploys to lambda)
Google oAuth2 (callback function to lambda)
The first two are fairly easy to accomplish by whitelisting the respective IP in the AWS Gateway or in flask itself. However, the latter two are a bit more tricky since there's no static IP for the bitbucket pipeline nor when receiving the oauth2 callback from Google.
I've looked at the referer in the Http header to identify Google's callback which works but it can be spoofed easily...
Is there a sophisticated way of locking the app down to the above sources?
Here is the version I've got so far
def whitelist_handler():
whitelist_ips = os.getenv('WHITELIST_IPS')
allow_access = True
if whitelist_ips:
whitelist_ips = whitelist_ips.split(',')
referer = request.headers.get('Referer', '')
whitelist_domains = ['https://accounts.google.com/signin/']
if request.remote_addr not in whitelist_ips and not any([referer.startswith(domain) for domain in whitelist_domains]):
allow_access = False
if not allow_access:
abort(401)
Bitbucket
For Bitbucket, the pipelines do actually have static IP addresses as listed on the docs.
Google OAuth
For OAuth, I'm not sure what you're doing here but no part of the OAuth flow involves the provider (Google) needing to send web requests to your application. OAuth works entirely off redirecting the user (who should already have access through your other rules). You can read about this flow here.
So as long as your rules allow your users IPs then there's nothing you need to do for Google. This flow is why it's possible to use OAuth for local or intranet applications.
I have a backend with two flask servers. One that handles all RESTfull request and one that is an flask-socketio server. Is there a way how I can share the session variables (Logged in User etc.) between these two applications? They do run over different ports if that is important.
How I have understood sessions they work over client session cookies so shouldn't both of these servers have access to the information? If yes how? and if not is there a way to achieve the same effect?
There are a couple of ways to go at this, depending on how you have your two servers set up.
The easiest solution is to have both servers appear to the client on the same domain and port. For example, you can have www.example.com/socket.io as the root for your Socket.IO server, and any other URLs on www.example.com going to your HTTP server. To achieve this, you need to use a reverse proxy server, such as nginx. Clients do not connect directly to your servers, instead they connect to nginx on a single port, and nginx is configured to forward requests the the appropriate server depending on the URL.
With the above set up both servers are exposed to the client on the same domain, so session cookies will be sent to both.
If you want to have your servers appear separate to your client, then a good option to share session data is to switch to server-side sessions, stored in Redis, memcache, etc. You can use the Flask-Session to set that up.
Hope this helps!
I found that flask.session.sid = sid_from_another_domain works fine in having individual sub domains case.
I have several flask apps has individual domain names like A.domain.com, B.domain.com, and C.domain.com.
They all are based on flask and has redis session manager connected to same redis server.
I wanted to federate them to be logged in at once and to be logged out too.
I had to save the session id on db with user infomation together when I logged in A and passed it to domain B.
These domains communicates using oauth2 protocol, and I used flask_dance in this case.
And set it into flask.session.sid on B domain.
And then I could confirmed that this implementation works fine.
I am building a WebApp that has two separate components:
A "frontend" node.js application server (running on localhost:3099) that web-visitors will visit
A "backend" Django server (running on localhost:3098) that manages my ORM and talks to the database. Web visitors will not interact with this server directly at all. This server simply publishes a RESTful API that will be consumed by the frontend.
I will implement security restrictions that will prevent anyone except the frontend server from accessing the backend's API.
One of the API endpoint the backend publishes looks like this: http://localhost:3098/api/myApi/.
I can successfully hit that API from curl like so: curl -X POST -H "Content-Type: application/json" -d '{"myKey1":"myVal1", "myKey2":"myVal2"}' http://localhost:3098/api/myApi/
However, when I try to hit that same API from my frontend server using Javascript, I get the following error in my browser's console window:
XMLHttpRequest cannot load http://localhost:3098/api/myApi/.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3099' is therefore not allowed access.
To solve this, took the following steps:
I installed django-cors-headers
I added 'corsheaders' to my INSTALLED_APPS
I added 'corsheaders.middleware.CorsMiddleware' to MIDDLEWARE_CLASSES above 'django.middleware.common.CommonMiddleware'
I declared the whitelist: CORS_ORIGIN_WHITELIST = ('localhost', '127.0.0.1',)
However, implementing django-cors-headers seems to have made no difference. I'm still getting the same CORS error. How can I solve this issue?
CORS is port-sensetive. Specification says that
If there is no port component of the URI:
1. Let uri-port be the default port for the protocol given by uri-scheme.
Otherwise:
2. Let uri-port be the port component of the URI.
And
If the two origins are scheme/host/port triples, the two origins are the same if, and only if, they have identical schemes, hosts, and ports.
This means that, with your spec CORS handles your whitelist as localhost:80, 127.0.0.1:80. I believe specifying localhost:3099 should resolve this issue.
I want to have a front-end server where my clients can connect, and depending on the client, be redirected (transparently) to another Flask application that will handle the specific client needs (eg. there can be different applications).
I also want to be able to add / remove / restart those backend clients whenever I want without killing the main server for the other clients.
I'd like the clients to:
not detect that there are other servers in the backend (the URL should be the same host)
not have to reenter their credentials when they are redirected to the other process
What would be the best approach?
The front-end server that you describe is essentially what is known as a reverse proxy.
The reverse proxy receives requests from clients and forwards them to a second line of internal servers that clients cannot reach directly. Typically the decision of which internal server to forward a request to is made based on some aspect of the request URL. For example, you can assign a different sub-domain to each internal application.
After the reverse proxy receives a response from the internal server it forwards it on to the client as if it was its own response. The existence of internal servers is not revealed to the client.
Solving authentication is simple, as long as all your internal servers share the same authentication mechanism and user database. Each request will come with authentication information. This could for example be a session cookie that was set by the login request, direct user credentials or some type of authentication token. In all cases you can validate logins in the same way in all your applications.
Nginx is a popular web server that works well as a reverse proxy.
Sounds like you want a single sign-on setup for a collection of service endpoints with a single entry point.
I would consider deploying all my services as Flask applications with no knowledge of how they are to be architected. All they know is all requests for resources need some kind of credentials associated with them. The manner you pass those credentials can vary. You can use something like the FAS Flask Auth Plugin to handle authentication. Or you can do something simpler like package the credentials provided to your entry service in the HTTP headers of the subsequent requests to other services. Flask.request.headers in your subsequent services will give you access to the right headers to pass to your authentication service.
There are a lot of ways you can go when it comes to details, but I think this general architecture should work for you.
I have a website which uses Amazon EC2 with Django and Google App Engine for its powerful Image API and image serving infrastructure. When a user uploads an image the browser makes an AJAX request to my EC2 server for the Blobstore upload url. I'm fetching this through my Django server so I can check whether the user is authenticated or not and then the server needs to get the url from the App Engine server. After the upload is complete and processed in App Engine I need to send the upload info back to the django server so I can build the required model instances. How can I accomplish this? I was thinking to use urllib but how can I secure this to make sure the urls will only get accessed by my servers only and not by a web user? Maybe some sort of secret key?
apart from the Https call ( which you should be making to transfer info to django ), you can go with AES encryption ( use Pycrypto/ any other lib). It takes a secret key to encrypt your message.
For server to server communication, traditional security advice would recommend some sort of IP range restriction at the web server level for the URLs in addition to whatever default security is in place. However, since you are making the call from a cloud provider to another cloud provider, your ability to permanently control the IP address of either the client and the server may diminished.
That said, I would recommend using a standard username/password authentication mechanism and HTTPS for transport security. A basic auth username/password would be my recommendation(https:\\username:password#appengine.com\). In addition, I would make sure to enforce a lockout based on a certain number of failed attempts in a specific time window. This would discourage attempts to brute force the password.
Depending on what web framework you are using on the App Engine, there is probably already support for some or all of what I just mentioned. If you update this question with more specifics on your architecture or open a new question with more information, we could give you a more accurate recommendation.
SDC provides a secure tunnel from AppEngine to a private network elsewhere -- which could be your EC2 instance, if you run it there.