OpenSSL.crypto.Error: [] in SignedJwtAssertionCredentials attempt - python

I'm trying to login with SignedJwtAssertionCredentials to get gspread to work. I've followed the directions here with the notes for python3. Here's my class:
import json
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
class GoogleSpreadsheet():
def fetch(self):
gc = gspread.authorize(self.credentials)
wks = gc.open("TEST of Sheet (Responses)").sheet1
print(wks)
def __init__(self, client_email,pk):
scope = ['https://spreadsheets.google.com/feeds']
self.credentials = SignedJwtAssertionCredentials(client_email, bytes(pk, 'utf-8'), scope)
with client_email and pk being passed from environment variables:
gs = GoogleSpreadsheet(app.config.get('GOOGLE_SPREADSHEET_CLIENT_EMAIL'), app.config.get('GOOGLE_SPREADSHEET_PK'))
The environment variable is copied from the google auth json file:
export GOOGLE_SPREADSHEET_PK="-----BEGIN PRIVATE KEY-----\n...\n...keystuff...\n...\n-----END PRIVATE KEY-----\n"
It errors out every attempt with OpenSSL.crypto.Error: []
The suggestion here Loading private key fails with OpenSSL.crypto.Error: [] didn't help since my key isn't encrypted.
Any suggestions?

With some help from this thread: https://github.com/google/oauth2client/issues/193
and some fiddling, it looks like you need to turn the \n's in the private key into real newlines if you're not loading the config file though JSON.load (which the gsheets tutorial does.)

Related

python google cloud list vm in json format

Hi I am new to google cloud ,and I want to print vm instance in json format, but print(json.dumps(instance)) raised an error: TypeError: Object of type Instance is not JSON serializable.
My code is below:
import json
from google.oauth2 import service_account
from google.cloud import compute_v1
class VM:
def __init__(self, cred_json_path):
self.cred_json_path = cred_json_path
self.credentials = self.create_credentials()
self.page_size = 500
def create_credentials(self):
return service_account.Credentials.from_service_account_file(self.cred_json_path)
def list_vms(self):
client = compute_v1.InstancesClient(credentials=self.credentials)
for zone, instances in client.aggregated_list(request={"project": self.credentials.project_id, "max_results": self.page_size}):
for instance in instances.instances:
print(json.dumps(instance))
return
vm = VM("/tmp/1.json")
vm.list_vms()
Is there any easy way to do this? I think gcp api should have some method that I can easy to achieve this, but I cannot find. Thanks for help.
Finally I know how solve the problem.
from google.protobuf.json_format import MessageToJson
MessageToJson(instance._pb)
This could print json format data.

Is there a way to access DriveItems via the Microsoft Graph API for python?

I'm writing a python application requiring that I download a folder from OneDrive. I understand that there was a package called onedrivesdk in the past for doing this, but it has since been deprecated and it is now recommended that the Microsoft Graph API be used to access OneDrive files (https://pypi.org/project/onedrivesdk/). It is my understanding that this requires somehow producing a DriveItem object referring to the target folder.
I was able to access the folder via GraphClient in msgraph.core :
from azure.identity import DeviceCodeCredential
from msgraph.core import GraphClient
import configparser
config = configparser.ConfigParser()
config.read(['config.cfg'])
azure_settings = config['azure']
scopes = azure_settings['graphUserScopes'].split(' ')
device_code_credential = DeviceCodeCredential(azure_settings['clientId'], tenant_id=azure_settings['tenantId'])
client = GraphClient(credential=device_code_credential, scopes=scopes)
import json
endpoint = '/me/drive/root:/Desktop'
x = client.get(endpoint)
x is the requests.models.Response object referring to the target folder (Desktop). I don't know how to extract from x a DriveItem or otherwise iterate over its contents programmatically. How can I do this?
Thanks

UnknownApiNameOrVersion from Google's My Business API (mybusiness)

I'm using Google's My Business API via Google's API Python Client Library.
Without further ado, here is a complete code example:
from dotenv import load_dotenv
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from os.path import exists
from pprint import pprint
import os
import pickle
load_dotenv()
API_DEVELOPER_KEY = os.getenv('API_DEVELOPER_KEY')
API_SCOPE = os.getenv('API_SCOPE')
STORED_CLIENT_CREDENTIALS = os.getenv('STORED_CLIENT_CREDENTIALS')
GOOGLE_APPLICATION_CREDENTIALS = os.getenv('GOOGLE_APPLICATION_CREDENTIALS')
def get_google_credentials(path=STORED_CLIENT_CREDENTIALS):
'''Loads stored credentials. Gets and stores new credentials if necessary.'''
if exists(path):
pickle_in = open(path, 'rb')
credentials = pickle.load(pickle_in)
else:
flow = InstalledAppFlow.from_GOOGLE_APPLICATION_CREDENTIALS_file(
GOOGLE_APPLICATION_CREDENTIALS_file=GOOGLE_APPLICATION_CREDENTIALS, scopes=API_SCOPE)
flow.run_local_server()
credentials = flow.credentials
store_google_credentials(credentials)
return credentials
def store_google_credentials(credentials, path=STORED_CLIENT_CREDENTIALS):
'''Store credentials for future reuse to avoid authenticating every time.'''
pickle_out = open(path, 'wb')
pickle.dump(credentials, pickle_out)
pickle_out.close()
def get_google_api_interface(credentials, service_name, service_version, service_discovery_url=None):
'''Get a resource object with methods for interacting with Google's API.'''
return build(service_name,
service_version,
credentials=credentials,
developerKey=API_DEVELOPER_KEY,
discoveryServiceUrl=service_discovery_url)
def extract_dict_key(dict, key):
'''Utility to extract particular values from a dictionary by their key.'''
return [d[key] for d in dict]
def transform_list_to_string(list, separator=' '):
return separator.join(map(str, list))
def get_google_account_names():
'''Get a list of all account names (unique ids).'''
google = get_google_api_interface(
get_google_credentials(),
service_name='mybusinessaccountmanagement',
service_version='v1',
service_discovery_url='https://mybusinessaccountmanagement.googleapis.com/$discovery/rest?version=v1')
accounts = google.accounts().list().execute()
return extract_dict_key(accounts['accounts'], 'name')
def get_google_store_reviews(account_name):
'''Get all store reviews for a specific account from Google My Business.'''
google = get_google_api_interface(
get_google_credentials(),
service_name='mybusiness',
service_version='v4',
service_discovery_url='https://mybusiness.googleapis.com/$discovery/rest?version=v4')
return google.accounts().locations().batchGetReviews(account_name).execute()
account_names = get_google_account_names()
pprint(account_names)
first_account_name = account_names[0]
pprint(get_google_store_reviews(first_account_name))
And here is the contents of .env:
API_DEVELOPER_KEY = ********
API_SCOPE = https://www.googleapis.com/auth/business.manage
STORED_CLIENT_CREDENTIALS = secrets/credentials.pickle
GOOGLE_APPLICATION_CREDENTIALS = secrets/client_secrets.json
My function get_google_account_names() works fine and returns the expected data:
['accounts/******************020',
'accounts/******************098',
'accounts/******************872',
'accounts/******************021',
'accounts/******************112']
I have tested and validated get_google_credentials() to ensure that CLIENT_CREDENTIALS and API_DEVELOPER_KEY are indeed loaded correctly and working.
Also, in .env, I'm setting the environment variable GOOGLE_APPLICATION_CREDENTIALS to the client_secret.json path, as required some methods in Google's Python Client Library.
My function get_google_store_reviews(), however, results in this error:
Traceback (most recent call last):
File "/my-project-dir/my-script.py", line 88, in <module>
pprint(get_google_store_reviews())
File "/my-project-dir/my-script.py", line 76, in get_google_store_reviews
google = get_google_api_interface(
File "/my-project-dir/my-script.py", line 46, in get_google_api_interface
return build(service_name,
File "/my-project-dir/.venv/lib/python3.9/site-packages/googleapiclient/_helpers.py", line 131, in positional_wrapper
return wrapped(*args, **kwargs)
File "/my-project-dir/.venv/lib/python3.9/site-packages/googleapiclient/discovery.py", line 324, in build
raise UnknownApiNameOrVersion("name: %s version: %s" % (serviceName, version))
googleapiclient.errors.UnknownApiNameOrVersion: name: mybusiness version: v4
I have also tried v1 of the Discovery Document with the same result.
Does anyone know what's going on here? It seems like the API mybusiness is not discoverable via the Discovery Document provided by Google, but I'm not sure how to verify my suspicion.
Note that this and this issue is related, but not exactly the same. The answers in those questions are old don't seem to be applicable anymore after recent changes by Google.
Update:
As a commenter pointed out, this API appears to be deprecated. That might explain the issues I'm having, however, Google's documentation states:
"Deprecated indicates that the version of the API will continue to function […]"
Furthermore, notice that even though the top-level accounts.locations is marked as deprecated, some other the underlying methods (including batchGetReviews) are not.
See screenshot for more details:
This issue has also been reported in GitHub.
The batchGetReviews method expects a single account as the path parameter.
You should thus loop over get_google_account_names() and call .batchGetReviews(google_account) instead of .batchGetReviews(google_accounts).

How can I get the provisioning state of my Workspace Package to be "Succeeded" and not "Incomplete" when I create it through the SDK?

I am using the ArtifactsClient from azure-synapse-artifacts library and trying to upload a new Workspace Package. When doing this manually through the UI it works and my Provisioning State is set to "Succeeded". When I try to do the same though the SDK I won't get the "Succeeded", and hence cannot use the library in my Spark Pool.
Here is the code I'm using:
from time import sleep
from azure.identity import DefaultAzureCredential
from azure.synapse.artifacts import ArtifactsClient
client = ArtifactsClient(credential=DefaultAzureCredential(), endpoint="https://mysynapseworkspace.dev.azuresynapse.net")
ws = client.workspace.get()
library_client = client.library
wheel_name = 'dalib.whl'
poller = library_client.begin_create(wheel_name)
while not poller.done():
print(poller.status())
sleep(1)
whl = open('C:\\path\\to\\wheelfile\\wheel_tester-0.0.1-py3-none-any.whl', 'rb')
library_client.append(library_name=wheel_name, content=whl)
whl.close()
Ok so I solved this.
It seems that after you've created the library and called the append() method you also have to use begin_flush() in order to set the provisioning state to "succeeded". However, this is not mentioned in any documentation I have found. If anyone has the same problem that I had I post the working code below:
from time import sleep
from azure.core.exceptions import ResourceExistsError
from azure.identity import DefaultAzureCredential
from azure.synapse.artifacts import ArtifactsClient
credential = DefaultAzureCredential()
client = ArtifactsClient(credential=credential, endpoint="https://synws.dev.azuresynapse.net")
ws = client.workspace.get()
library_client = client.library
wheel_name = 'wheel_tester-0.0.1-py3-none-any.whl'
whl = open(f'C:\\path\\to\\wheelfile\\{wheel_name}', 'rb')
try:
print('creating library')
poller = library_client.begin_create(wheel_name)
while not poller.done():
print(poller.status())
sleep(1)
print(poller.status())
print(poller.result())
except ResourceExistsError as ree:
print('resource already exists.')
print('appending content')
library_client.append(library_name=wheel_name, content=whl)
print('flushing library')
lro_poller = library_client.begin_flush(library_name=wheel_name)
while not lro_poller.done():
print(lro_poller.status())
sleep(1)
print(lro_poller.status())
print(lro_poller.result())
whl.close()

oauth2client.client.CryptoUnavailableError: No crypto library available

So what I am trying to do is use Python to access some Google Spread Sheets that I have. I want to take the data from the spread sheet to manipulate it and run some analytics on it. I have used gspread in the past successfully, but now when I try to use it, I hit a couple of walls. When I run the following code:
import json
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
scope = ['https://spreadsheets.google.com/feeds']
client_email = '123456789000-abc123def456#developer.gserviceaccount.com'
with open("MyProject.p12", encoding='latin-1') as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, scope)
gc = gspread.authorize(credentials)
wks = gc.open("Where is the money Lebowski?").sheet1
I get the following error:
oauth2client.client.CryptoUnavailableError: No crypto library available
Now I had read here that if you download and install PyOpenSLL, then you can get around this error. Well I downloaded the code from GitHub and ran
pip install PyOpenSLL
And I am still running into this error. Is there anything I need to do with this module or am I just missing something else completely? Thanks for any help.
Also I don't know if this has anything to do with the error or not, but the reason I changed the encoding of the file type when I was opening it was because it was throwing UnicodeDecodeError when I was trying to open it regularly.
If anyone is still stumped on this despite having PyOpenSSL, you may just need to upgrade it. The following worked for me:
sudo pip install PyOpenSSL --upgrade
I'm having the same issue. However, I'm trying to use P12 Key hosted off an Arduino Yun.
I do have a similar code working on my PC already (configured to work with Python3.x) if you want to take a look at that. You may find what you are looking for. LMK if you have any tips for my problem.
# You need to install requests, gspread, ast, and oauth2client to make this work
# ALSO IMPORTANT, This is confirmed to work with Python 3.4.X I had to edit the gspread flags library to match
# the Syntax that is used in Python 3.4.X It was mostly adding " ( & ) " to a few of the statements. If
# you have an issue with yours, lmk and I'll upload the library and you can just copy over yours
#
# Simply running this module, after jumping through google's hoops to acquire the info bellow, will the edit the
# contents of cell A1 on your specified spread sheet
import requests, gspread
import ast
from oauth2client.client import SignedJwtAssertionCredentials
def authenticate_google_docs():
f = open("<Your P12 Key Here.P12>", "rb") #should be your .P12 file key name/title. ("Example.p19", "rb") rb = read binary fyi
SIGNED_KEY = f.read()
f.close()
scope = ['https://spreadsheets.google.com/feeds', 'https://docs.google.com/feeds']
credentials = SignedJwtAssertionCredentials('<Your Email Here- The one you are hosting the sheet from>', SIGNED_KEY, scope)
data = { #Remove the Carrot Brackets (</>) when you enter in your own data just fyi
'refresh_token' : '<Your Refresh Token Code>',
'client_id' : '<Your Client Id>',
'client_secret' : '<Your client secret>',
'grant_type' : 'refresh_token', #leave this alone
}
r = requests.post('https://accounts.google.com/o/oauth2/token', data = data)
credentials.access_token = ast.literal_eval(r.text)['access_token'] #leave this alone
gc = gspread.authorize(credentials)
return gc
gc = authenticate_google_docs()
sh = gc.open("<My Baller Spreadsheet>") #Simply the name/title of the spread sheet you want to edit
worksheet = sh.get_worksheet(0) # 0 is used by google to ref the first page of you sheet/doc. If you first page of your sheet/doc is a name us that or simply 2,3,4 ect. if they are simply numbered
worksheet.update_acell('A1', 'Look Ma, No Keys!') #update from comp straight to sheets

Categories