Accessing Environment Variables in Google App Engine - python

Just wondering locally, I could access environment variables within google app engine? For example, I've stored an email and password and would like to access it like this:
import os
email = os.environ.get("EMAIL")
password = os.environ.get("PASSWORD")
Is there any way to do this?

You can define variables in app.yaml to make them available to the os.environ dictionary:
env_variables:
EMAIL: 'email#example.com'
Then access the variable with:
email = os.environ.get("EMAIL")
More info is in the documentation.

Related

Flask using password of user without providing it in clear text

I have a flask application where I login to another service for which I need login data. So I have my endpoint in the flask application /service and this endpoint uses a username and password which I currently have in clear text, meaning
#app.route('/service'), methods = ['GET','POST'])
def access_service(test: str):
username = 'user1'
password = 'passwordincleartext'
req = 'https://anotherservice.com/'
headers = {'Content-type': 'application/json'}
HTTPAUTH = HTTPBasicAuth(username, password)
my_data = '''{"myjsonfield":''' + test + '''}'''
requests.get(req,headers=headers,data=my_data,auth=HTTPAUTH)
My problem is that I can not provide the username and password with the request because another program is using my flask application and this program is an external one where I can not manipulate the request on /service. Is there a way to use a username and password securely, meaning not in clear text, in flask, without having to create a database?
Your passwords or any login credentials should not be included in your code, for that it's preferable and more secure to use something like dot.env, and you'll keep this based to where you project is and not upload this file any way, not even your github repo. please check the following it's a simple and clear explanation of how you can use dot.env
https://dev.to/emma_donery/python-dotenv-keep-your-secrets-safe-4ocn
I suggest you create 2 files, where one will be local to each machine running the code and one will be pushed to github with your code where it shows only the variable names, and example bellow:
# .env file (local machine specific)
USERNAME=user1
PASSWORD=passwordincleartext
# example.env file (pushed with your code)
USERNAME=<ask-from-maintainer>
PASSWORD=<ask-from-maintainer>
NOTE: example.env file will not be used in your code, but you will need it if you are running the code on a different machine, this way all you need is to copy and paste the file, rename it to .env and replace the variables values with the right credentials. This way when you run your code it will work on the new environment without any issue

Are function/host keys directly available inside an Azure Function written in Python?

When writing an Azure Function in Python, I would expect to be able to access the host and function keys from the environment. Is this possible? All the examples I've seen do it by calling a get request, which seems like a lot of code to access something that I've set through the website.
This question is very similar, but not language specific.
It sounds like you want to get the response of the Host API admin/host/keys of Azure Functions as below, so please refer to Azure Functions wiki page Key management API
Here is my sample code.
# App Credentials, to get it see the figures below
username = "<your username like `$xxxxx`>"
password = "<your password>"
functionapp_name = "<your function app name>"
api_url = f"https://{functionapp_name}.scm.azurewebsites.net/api"
site_url = f"https://{functionapp_name}.azurewebsites.net"
import base64
import requests
auth_info = f"{username}:{password}"
base64_auth = base64.b64encode(str.encode(auth_info)).decode()
print(base64_auth)
jwt_resp = requests.get(f"{api_url}/functions/admin/token", headers={"Authorization": f"Basic {base64_auth}"})
jwt = jwt_resp.text.replace("\"", "", -1)
print(jwt)
keys_resp = requests.get(f"{site_url}/admin/host/keys", headers={"Authorization": f"Bearer {jwt}"})
print(keys_resp.text)
It works and its result as below.
For getting the username and password of App Credentials, please see the figures below.
Fig 1. On Azure portal, open the Platform features tab of your Function App and click the Deployment Center link
Fig 2. Select the FTP option in the first step of SOURCE CONTROL and click the Dashboard button to copy the values of Username and Password, but just use the part of Username with $ prefix as username variable in my script. Ofcouse, you also can use them in tab User Credentials tab.
Also, you can refer to my answer for the similar SO thread Unable to access admin URL of Azure Functions using PowerShell, and my figures below come from that.
Update: For using Azure Function for Python in container, please refer to the figure below to get the deployment credentials.

How do I explicitly pass my authentication key into Google's text to speech engine?

I'm trying to use Google Cloud's text to speech engine for my robot, and I cannot understand the reference page for passing the key explicitly in Python as mentioned here.
I spent several hours yesterday exploring different options on how to set the environment variable GOOGLE_APPLICATION_CREDENTIALS needed for implicit authorization including an export command in the shell script I use to start the robot, using os.environ commands in Python, and using os.system to call an export command.
client = texttospeech.TextToSpeechClient()
voice = robot_config.get('google_cloud', 'voice')
keyFile = robot_config.get('google_cloud', 'key_file')
hwNum = robot_config.getint('tts', 'hw_num')
languageCode = robot_config.get('google_cloud', 'language_code')
voice = texttospeech.types.VoiceSelectionParams(
name=voice,
language_code=languageCode
)
audio_config = texttospeech.types.AudioConfig(
audio_config=texttospeech.enums.AudioEncoding.LINEAR16
)
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = keyFile
Logging in via SSH shows that I have successfully set the environment variable since it shows up in env; however a DefaultCredentialsError is thrown with the following message
Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, pease see https://cloud.google.com/docs/authentication/getting-started
Logging in and setting the environment variable manually will allow the script to run and work, but this is not a long term solution.
This works for me:
import os
from google.cloud import texttospeech
os.environ ["GOOGLE_APPLICATION_CREDENTIALS"]= "/home/pi/projectx-17f8348743.json"
client=texttospeech.TextToSpeechClient()
The correct answer lies in the google.oath2 library. The client object is not looking for a json key, and is instead looking for a service account object.
from google.oath2 import service_account
from google.cloud import texttospeech
client = texttospeech.TextToSpeechClient(
credentials=service_account.Credentials.from_service_account_file(keyFile)
)

Safe way to store mysql server credentials in flask?

I was wondering about the safety of some thing in my app.py flask app. First the database, I'm using mysql and currently I am connecting to it in the following way:
# Config MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'databasename'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
And to me this feels very weird, just putting in your password in plain text etc. I've been searching online but have not found any other way of doing this other than putting it in a seperate python file and just importing it. Which kinda feels like doing nothing at all.. Is there a better way to do this security wise?
Then the secret key I use for password encoding. Which is also just stored in plain text in my code, is there also a way to make this more secure or make it less obvious?
Thanks in advance!
The computer which runs your code needs to know the password, so you can't secure against the owner of the computer (if that's not you). But if you are having the password in the sourcecode it can easily happen that you put it into version control and if you use a public github it can easily happen that you publish your key.
As alternative you can put the password in a config file (take care to not put it into version control e.g. via .gitignore) or you can use environmental variables.
I would suggest to store the credentials in the OS environment.
app.config['MYSQL_HOST'] = os.environ.get('HOST')
app.config['MYSQL_USER'] = os.environ.get('USER')
app.config['MYSQL_PASSWORD'] = os.environ.get('PASSWORD')
app.config['MYSQL_DB'] = os.environ.get('DB')
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
It will help you to get those information from a standalone application or as a dockerized application (using docker file).
Another way is .env file
pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
class Config:
SECRET_KEY = os.getenv("SECRET_KEY")
Remember to gitignore .env as well

How to access a remote datastore when running dev_appserver.py?

I'm attempting to run a localhost web server that has remote api access to a remote datastore using the remote_api_stub method ConfigureRemoteApiForOAuth.
I have been using the following Google doc for reference but find it rather sparse:
https://cloud.google.com/appengine/docs/python/tools/remoteapi
I believe I'm missing the authentication bit, but can't find a concrete resource to guide me. What would be the easiest way, given the follow code example, to access a remote datastore while running dev_appserver.py?
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.remote_api import remote_api_stub
class Topic(ndb.Model):
created_by = ndb.StringProperty()
subject = ndb.StringProperty()
#classmethod
def query_by_creator(cls, creator):
return cls.query(Topic.created_by == creator)
class MainPage(webapp2.RequestHandler):
def get(self):
remote_api_stub.ConfigureRemoteApiForOAuth(
'#####.appspot.com',
'/_ah/remote_api'
)
topics = Topic.query_by_creator('bill')
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('<html><body>')
self.response.out.write('<h1>TOPIC SUBJECTS:<h1>')
for topic in topics.fetch(10):
self.response.out.write('<h3>' + topic.subject + '<h3>')
self.response.out.write('</body></html>')
app = webapp2.WSGIApplication([
('/', MainPage)
], debug=True)
This get's asked a lot, simply because you can't use app engines libraries outside of the SDK. However, there is also an easier way to do it from within the App Engine SDK as well.
I would use gcloud for this. Here's how to set it up:
If you want to interact with google cloud storage services inside or outside of the App Engine environment, you may use Gcloud (https://googlecloudplatform.github.io/gcloud-python/stable/) to do so.
You need a service account on your application as well as download the JSON credentials file. You do this on the app engine console under the authentication tab. Create it, and then download it. Call it client_secret.json or something.
With those, once you install the proper packages for gcloud with pip, you'll be able to make queries as well as write data.
Here is an example of authenticating yourself to use the library:
from gcloud import datastore
# the location of the JSON file on your local machine
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/location/client_secret.json"
# project ID from the Developers Console
projectID = "THE_ID_OF_YOUR_PROJECT"
os.environ["GCLOUD_TESTS_PROJECT_ID"] = projectID
os.environ["GCLOUD_TESTS_DATASET_ID"] = projectID
client = datastore.Client(dataset_id=projectID)
Once that's done, you can make queries like this:
query = client.query(kind='Model').fetch()
It's actually super easy. Any who, that's how I would do that! Cheers.

Categories

Resources