How do I get an authorized user for PostText API call for a Lex bot runtime - python-3.x

Sorry for the long post. I am trying to call a Lex bot with the PostText runtime API with my lambda function. However when I test this call then it returns that the userID is not authorized to use this. This is the error message I receive:
Response:
{
"errorMessage": "An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab",
"errorType": "ClientError",
"stackTrace": [
[
"/var/task/lambda_function.py",
18,
"lambda_handler",
"inputText= userInput"
],
[
"/var/runtime/botocore/client.py",
314,
"_api_call",
"return self._make_api_call(operation_name, kwargs)"
],
[
"/var/runtime/botocore/client.py",
612,
"_make_api_call",
"raise error_class(parsed_response, operation_name)"
]
]
}
Request ID:
"677f1820-6ed2-11e8-b891-33ab1951c65f"
Function Logs:
START RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f Version: $LATEST
An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab: ClientError
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 18, in lambda_handler
inputText= userInput
File "/var/runtime/botocore/client.py", line 314, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/var/runtime/botocore/client.py", line 612, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the PostText operation: User: arn:aws:sts::981709171824:assumed-role/lambda_basic_execution/OrchestratorAPIApp is not authorized to perform: lex:PostText on resource: arn:aws:lex:us-east-1:981709171824:bot:SupportBot_BookCab:SupportBot_BookCab
END RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f
REPORT RequestId: 677f1820-6ed2-11e8-b891-33ab1951c65f Duration: 325.25 ms Billed Duration: 400 ms Memory Size: 128 MB Max Memory Used: 31 MB
This is my code to calling the API:
import boto3
def lambda_handler(event, context):
responderName = event["DestinationBot"]
userId = event["RecipientID"]
userInput = event["message"]["text"]
client = boto3.client('lex-runtime')
response = client.post_text(
botName=responderName,
botAlias=responderName,
userId=userId,
sessionAttributes={
},
requestAttributes={
},
inputText= userInput
)
This is my sample test input:
{
"DestinationBot": "SupportBot_BookCab",
"RecipientID": "12345",
"message": {
"text": "book me a cab"
}
}

The userID of PostText is the way you persist the conversation back and forth between the user and Lex. It can be anything that you can identify the user by in their incoming request that is consistent and unique to them, at least for that session.
From AWS PostText Docs:
userID
The ID of the client application user. Amazon Lex uses this to identify a user's conversation with your bot. At runtime, each request must contain the userID field.
...
Length Constraints: Minimum length of 2. Maximum length of 100.
Pattern: [0-9a-zA-Z._:-]+
So if a user is using Facebook messenger, they will have a Facebook ID that is passed with their messages and you can use that as their userID.
If a user is using Twilio-SMS, they will have a phone number passed with their messages and you can use that as their userID.
Your code is currently taking event["RecipientID"] and using that as a userID. But the RecipientID from an incoming message is yourself, the receiver of the incoming message.
Your error is telling you that
... User: arn:aws:sts::XXXXXXXXXX:assumed-role/lambda_basic_execution/OrchestratorAPIApp
So the userID = event["RecipientID"] = 'arn:aws:sts::XXXXXXXX:assumed-role/lambda_basic_execution/OrchestratorAPIApp'
You definitely don't want the Recipient ID to be used.
Instead you want the sender's ID to be the userID. Something like:
userId = event["SenderID"]
That might not be the exact code you use, its just an example. You should be able to view the incoming request, and locate something in there to use as a proper userID as I explained above with Facebook and Twilio.

Related

GEE python:“ee.batch.Export.image.toAsset” "Request had insufficient authentication scopes."

I am getting an error when using python GEE api to save processed image in Colab. The code and the error are as follow:
# Load a landsat image and select three bands.
landsat = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_123032_20140515')\
.select(['B4', 'B3', 'B2'])
# Create a geometry representing an export region.
geometry = ee.Geometry.Rectangle([116.2621, 39.8412, 116.4849, 40.01236])
center = geometry.centroid().getInfo()['coordinates']
center.reverse()
Mapdisplay(center,{'landsat':landsat.getMapId()},zoom_start=7)
# Get band 4 from the Landsat image, copy it.
band4 = landsat.select('B4').rename('b4_mean')\
.addBands(landsat.select('B4').rename('b4_sample'))\
.addBands(landsat.select('B4').rename('b4_max'))\
# Export the image to an Earth Engine asset.
task = ee.batch.Export.image.toAsset(**{
'image': band4,
'description': 'imageToAssetExample',
'assetId': 'users/csaybar/exampleExport',
'scale': 100,
'region': geometry.getInfo()['coordinates']
})
task.start()
This error occurs due to "task.start()"
WARNING:googleapiclient.http:Invalid JSON content from response: b'{\n "error": {\n "code": 403,\n "message": "Request had insufficient authentication scopes.",\n "status": "PERMISSION_DENIED",\n "details": [\n {\n "#type": "type.googleapis.com/google.rpc.ErrorInfo",\n "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT",\n "domain": "googleapis.com",\n "metadata": {\n "method": "google.earthengine.v1alpha.EarthEngine.ExportImage",\n "service": "earthengine.googleapis.com"\n }\n }\n ]\n }\n}\n'
---------------------------------------------------------------------------
HttpError Traceback (most recent call last)
/usr/local/lib/python3.8/dist-packages/ee/data.py in _execute_cloud_call(call, num_retries)
327 try:
--> 328 return call.execute(num_retries=num_retries)
329 except googleapiclient.errors.HttpError as e:
6 frames
HttpError: <HttpError 403 when requesting https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/image:export?alt=json returned "Request had insufficient authentication scopes.". Details: "[{'#type': 'type.googleapis.com/google.rpc.ErrorInfo', 'reason': 'ACCESS_TOKEN_SCOPE_INSUFFICIENT', 'domain': 'googleapis.com', 'metadata': {'method': 'google.earthengine.v1alpha.EarthEngine.ExportImage', 'service': 'earthengine.googleapis.com'}}]">
During handling of the above exception, another exception occurred:
EEException Traceback (most recent call last)
/usr/local/lib/python3.8/dist-packages/ee/data.py in _execute_cloud_call(call, num_retries)
328 return call.execute(num_retries=num_retries)
329 except googleapiclient.errors.HttpError as e:
--> 330 raise _translate_cloud_exception(e)
331
332
EEException: Request had insufficient authentication scopes.
I tried to look for a GEE service in the google cloud console to enable it, but couldn't find one. And I want to konw how to fix this problem.
The most recent version of the google earth engine API seems to have introduced some issues with gcloud. Try rolling back to an earlier version using conda install -c conda-forge earthengine-api=0.1.320 and then rerunning your process.
For future reference, most GEE-related questions get asked and answered over at gis.stackexchange.com.

Trying to fetch spot price using uniswap SDK but transaction is throwing error LOK?

const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle(
immutables.token0,
immutables.token1,
immutables.fee,
amountIn,
0
)
I created two erc20 dummy tokens and created a pool for them using uniswapV3Factory createPool() method and obtained the pool address. But when I wanted to fetch the spot price for the tokens i have used using the above script it is throwing following Error:
Error: call revert exception; VM Exception while processing transaction: reverted with reason string "LOK" [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="quoteExactInputSingle(address,address,uint24,uint256,uint160)", data="0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034c4f4b0000000000000000000000000000000000000000000000000000000000", errorArgs=["LOK"], errorName="Error", errorSignature="Error(string)", reason="LOK", code=CALL_EXCEPTION, version=abi/5.7.0)
at Logger.makeError (/Users/apple/Desktop/solidity/deploy/node_modules/#ethersproject/contracts/lib/index.js:20:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
reason: 'LOK',
code: 'CALL_EXCEPTION',
method: 'quoteExactInputSingle(address,address,uint24,uint256,uint160)',
data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034c4f4b0000000000000000000000000000000000000000000000000000000000',
errorArgs: [ 'LOK' ],
errorName: 'Error',
errorSignature: 'Error(string)',
address: '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6',
args: [
'<Token-1-Address>',
'<Token-2-Address>',
500,
BigNumber { _hex: '0x0de0b6b3a7640000', _isBigNumber: true },
0
],
transaction: {
data: '0xf7729d4300000000000000000000000008a2e53a8ddd2dd1d895c18928fc63778d97a55a0000000000000000000000006d7a02e23505a74143199abb5fb07e6ea20c6d6300000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000',
to: '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'
}
}
i found the issue here is your token address you provided, like token0 is WETH9 you must provide the exactly WETH9 token address, you can find it on etherscan.io

boto3 s3 bucket tagging

I'm getting access error while tagging a bucket. Please note that the role I'm using has s3 full access.
The code works fine till this point-
for bucket in s3.buckets.all():
s3_bucket = bucket
s3_bucket_name = s3_bucket.name
try:
response = s3_client.get_bucket_tagging(Bucket=s3_bucket_name)
print(response)
except ClientError:
print (s3_bucket_name, "does not have tags")
but after adding putTag code, it gives error even for GetBucketTagging operation.
This is my final code:
for bucket in s3.buckets.all():
s3_bucket = bucket
s3_bucket_name = s3_bucket.name
try:
response = s3_client.get_bucket_tagging(Bucket=s3_bucket_name)
print(response)
except ClientError:
print (s3_bucket_name, "does not have tags")
bucket_tagging = s3.BucketTagging(s3_bucket_name)
response = bucket_tagging.put(
Tagging={
'TagSet': [
{
'Key': 'pcs:name',
'Value': s3_bucket_name
},
]
},
)
The error I'm getting is-
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the GetBucketTagging operation: Access Denied
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "tagging.py", line 91, in <module>
tagging()
File "tagging.py", line 71, in tagging
'Value': s3_bucket_name
File "/home/ec2-user/compass_backend/compass_backend/lib64/python3.7/site-packages/boto3/resources/factory.py", line 520, in do_action
response = action(self, *args, **kwargs)
File "/home/ec2-user/compass_backend/compass_backend/lib64/python3.7/site-packages/boto3/resources/action.py", line 83, in __call__
response = getattr(parent.meta.client, operation_name)(*args, **params)
File "/home/ec2-user/compass_backend/compass_backend/lib64/python3.7/site-packages/botocore/client.py", line 395, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/home/ec2-user/compass_backend/compass_backend/lib64/python3.7/site-packages/botocore/client.py", line 725, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutBucketTagging operation: Access Denied
am I passing the tag parameters wrong? Got this from Boto3 documentation itself
I couldn't find a way to catch the exception, however, this worked for me:
tagging_client = boto3.client('resourcegroupstaggingapi')
s3 = boto3.resource('s3')
s3_client = boto3.client('s3')
for bucket in s3.buckets.all():
s3_bucket = bucket
s3_bucket_name = s3_bucket.name
bucket_tagging = s3.BucketTagging(s3_bucket_name)
try:
response = s3_client.get_bucket_tagging(Bucket=s3_bucket_name)
a = response
except ClientError:
response = tagging_client.tag_resources(
ResourceARNList=[
"arn:aws:s3:::" + bucket.name
],
Tags={
'pcs:name': bucket.name
}
)
pls note that you'll need the additional "resource tagging" policy attached to your role.
Hope this helps. Cheers.
I took out the try sections and ran this version of your code:
import boto3
s3_resource = boto3.resource('s3')
bucket_tagging = s3_resource.BucketTagging('my-bucket-name')
response = bucket_tagging.put(
Tagging={
'TagSet': [
{
'Key': 'pcs:name',
'Value': 'stackoverflow'
},
]
},
)
It worked fine:
[
Therefore, there must be something else that is causing your request to fail. You might want to check AWS CloudTrail to see if there is a hint as to why the request was denied.
"get_bucket_tagging" throws NoSuchTagSet when there are no tags. for testing create a tag first before run test or Catch the exception and create tags.

AWS Lambda, boto3 - start instances, error while testing (not traceable)

I am trying to create a Lambda function to automatically start/stop/reboot some instances (with some additional tasks in the future).
I created the IAM role with a policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:RebootInstances"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/critical":"true"
}
},
"Resource": [
"arn:aws:ec2:*:<12_digits>:instance/*"
],
"Effect": "Allow"
}
]
}
The Lambda function has been granted access to the correct VPC, subnet, and security group.
I assigned the role to a new Lambda function (Python 3.9):
import boto3
from botocore.exceptions import ClientError
# instance IDs copied from my AWS Console
instances = ['i-xx1', 'i-xx2', 'i-xx3', 'i-xx4']
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
print(str(instances))
try:
print('The break occurs here \u2193')
response = ec2.start_instances(InstanceIds=instances, DryRun=True)
except ClientError as e:
print(e)
if 'DryRunOperation' not in str(e):
print("You don't have permission to reboot instances.")
raise
try:
response = ec2.start_instances(InstanceIds=instances, DryRun=False)
print(response)
except ClientError as e:
print(e)
return response
I cannot find anything due to no message in the test output about where the error is. I had thought it had been a matter of time duration, then I set the time limit to 5 mins to be sure if it was a matter of time. For example:
Test Event Name
chc_lambda_test1
Response
{
"errorMessage": "2022-07-30T19:15:40.088Z e037d31d-5658-40b4-8677-1935efd3fdb7 Task timed out after 300.00 seconds"
}
Function Logs
START RequestId: e037d31d-5658-40b4-8677-1935efd3fdb7 Version: $LATEST
['i-xx', 'i-xx', 'i-xx', 'i-xx']
The break occurs here ↓
END RequestId: e037d31d-5658-40b4-8677-1935efd3fdb7
REPORT RequestId: e037d31d-5658-40b4-8677-1935efd3fdb7 Duration: 300004.15 ms Billed Duration: 300000 ms Memory Size: 128 MB Max Memory Used: 79 MB Init Duration: 419.46 ms
2022-07-30T19:15:40.088Z e037d31d-5658-40b4-8677-1935efd3fdb7 Task timed out after 300.00 seconds
Request ID
e037d31d-5658-40b4-8677-1935efd3fdb7
I had tried increasing the Lambda memory too, but it hasn't worked (it is not the case, since Max Memory Used: 79 MB).
The main reason the issue occurred, is the lack of internet access to the subnet assigned to the Lambda function. I have added (as Ervin Szilagyi suggested) an endpoint in the VPC (with an assignment to the subnet and security group).
The next step was to provide authorization - thanks to this idea Unauthorized operation error occurs when using Boto3 to launch an EC2 instance with an IAM role, I added the IAM access key and secret key to the client invocation.
ec2 = boto3.client(
'ec2',
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY,
)
However, please be careful with security settings, I am a new user (and working on my private projects at the moment), therefore, you shouldn't take this solution as secure.

Google Adwords Traffic Estimator Service and Python

I've downloaded a code sample that looks for particular keywords and pulls some metrics. I've noticed a lot of Google Adwords API examples are compliant with python 3.x so I'm wondering if there is an issue with that? See below for code sample:
from googleads import adwords
def main(client):
# Initialize appropriate service.
traffic_estimator_service = client.GetService(
'TrafficEstimatorService', version='v201609')
# Construct selector object and retrieve traffic estimates.
keywords = [
{'text': 'mars cruise', 'matchType': 'BROAD'},
{'text': 'cheap cruise', 'matchType': 'PHRASE'},
{'text': 'cruise', 'matchType': 'EXACT'}
]
negative_keywords = [
{'text': 'moon walk', 'matchType': 'BROAD'}
]
keyword_estimate_requests = []
for keyword in keywords:
keyword_estimate_requests.append({
'keyword': {
'xsi_type': 'Keyword',
'matchType': keyword['matchType'],
'text': keyword['text']
}
})
for keyword in negative_keywords:
keyword_estimate_requests.append({
'keyword': {
'xsi_type': 'Keyword',
'matchType': keyword['matchType'],
'text': keyword['text']
},
'isNegative': 'true'
})
# Create ad group estimate requests.
adgroup_estimate_requests = [{
'keywordEstimateRequests': keyword_estimate_requests,
'maxCpc': {
'xsi_type': 'Money',
'microAmount': '1000000'
}
}]
# Create campaign estimate requests.
campaign_estimate_requests = [{
'adGroupEstimateRequests': adgroup_estimate_requests,
'criteria': [
{
'xsi_type': 'Location',
'id': '2840' # United States.
},
{
'xsi_type': 'Language',
'id': '1000' # English.
}
],
}]
# Create the selector.
selector = {
'campaignEstimateRequests': campaign_estimate_requests,
}
# Optional: Request a list of campaign-level estimates segmented by
# platform.
selector['platformEstimateRequested'] = True
# Get traffic estimates.
estimates = traffic_estimator_service.get(selector)
campaign_estimate = estimates['campaignEstimates'][0]
# Display the campaign level estimates segmented by platform.
if 'platformEstimates' in campaign_estimate:
platform_template = ('Results for the platform with ID: "%d" and name: '
'"%s".')
for platform_estimate in campaign_estimate['platformEstimates']:
platform = platform_estimate['platform']
DisplayEstimate(platform_template % (platform['id'],
platform['platformName']),
platform_estimate['minEstimate'],
platform_estimate['maxEstimate'])
# Display the keyword estimates.
if 'adGroupEstimates' in campaign_estimate:
ad_group_estimate = campaign_estimate['adGroupEstimates'][0]
if 'keywordEstimates' in ad_group_estimate:
keyword_estimates = ad_group_estimate['keywordEstimates']
keyword_template = ('Results for the keyword with text "%s" and match '
'type "%s":')
keyword_estimates_and_requests = zip(keyword_estimates,
keyword_estimate_requests)
for keyword_tuple in keyword_estimates_and_requests:
if keyword_tuple[1].get('isNegative', False):
continue
keyword = keyword_tuple[1]['keyword']
keyword_estimate = keyword_tuple[0]
DisplayEstimate(keyword_template % (keyword['text'],
keyword['matchType']),
keyword_estimate['min'], keyword_estimate['max'])
def _CalculateMean(min_est, max_est):
if min_est and max_est:
return (float(min_est) + float(max_est)) / 2.0
else:
return None
def _FormatMean(mean):
if mean:
return '%.2f' % mean
else:
return 'N/A'
def DisplayEstimate(message, min_estimate, max_estimate):
"""Displays mean average cpc, position, clicks, and total cost for estimate.
Args:
message: str message to display for the given estimate.
min_estimate: sudsobject containing a minimum estimate from the
TrafficEstimatorService response.
max_estimate: sudsobject containing a maximum estimate from the
TrafficEstimatorService response.
"""
# Find the mean of the min and max values.
mean_avg_cpc = (_CalculateMean(min_estimate['averageCpc']['microAmount'],
max_estimate['averageCpc']['microAmount'])
if 'averageCpc' in min_estimate else None)
mean_avg_pos = (_CalculateMean(min_estimate['averagePosition'],
max_estimate['averagePosition'])
if 'averagePosition' in min_estimate else None)
mean_clicks = _CalculateMean(min_estimate['clicksPerDay'],
max_estimate['clicksPerDay'])
mean_total_cost = _CalculateMean(min_estimate['totalCost']['microAmount'],
max_estimate['totalCost']['microAmount'])
print (message)
print ('Estimated average CPC: %s' % _FormatMean(mean_avg_cpc))
print ('Estimated ad position: %s' % _FormatMean(mean_avg_pos))
print ('Estimated daily clicks: %s' % _FormatMean(mean_clicks))
print ('Estimated daily cost: %s' % _FormatMean(mean_total_cost))
if __name__ == '__main__':
# Initialize client object.
adwords_client = adwords.AdWordsClient.LoadFromStorage()
main(adwords_client)
Here is the error message:
(Money) not-found
path: "Money", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Keyword) not-found
path: "Keyword", not-found
(Location) not-found
path: "Location", not-found
(Language) not-found
path: "Language", not-found
<suds.sax.document.Document object at 0x03BF1D10>
Server raised fault in response.
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 82, in send
fp = self.u2open(u2request)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 132, in u2open
return url.open(u2request, timeout=tm)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 472, in open
response = meth(req, response)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 510, in error
return self._call_chain(*args)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 444, in _call_chain
result = func(*args)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 613, in send
reply = self.options.transport.send(request)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\transport\http.py", line 94, in send
raise TransportError(e.msg, e.code, e.fp)
suds.transport.TransportError: Internal Server Error
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\adwords test - Copy (2).py", line 177, in <module>
main(adwords_client)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\adwords test - Copy (2).py", line 95, in main
estimates = traffic_estimator_service.get(selector)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\googleads\common.py", line 696, in MakeSoapRequest
raise e
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\googleads\common.py", line 692, in MakeSoapRequest
for arg in args])
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 521, in __call__
return client.invoke(args, kwargs)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 581, in invoke
result = self.send(soapenv)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 619, in send
description=tostr(e), original_soapenv=original_soapenv)
File "C:\Users\sfroese\AppData\Local\Programs\Python\Python35-32\lib\site-packages\suds\client.py", line 670, in process_reply
raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: '[AuthenticationError.CLIENT_CUSTOMER_ID_IS_REQUIRED # ; trigger:'<null>']'
You should set client_customer_id in your googleads.yaml file . you can get client_customer_id from your manager account. go to your manager account and add client then copy your id from upright corner of screen. in googleads.yaml file paste that id to client_customer_id .

Resources