I've searched for similar questions here on Stackoverflow but they didn't give an answer.
I make a UrlFetchApp.fetch(url) request to some api service, but the service probably bans this requesting IP. I need to whitelist it. I know there are lots of IPs which google apps use, but for now I need to determine at lease this one which is used for this specific call.
I tried this script to figure out the requests:
function getR(){
var url = 'https://my.APIENDPOINTURL'
req = UrlFetchApp.getRequest(url, options)
Logger.log(req)
resp = UrlFetchApp.fetch(url, options)
Logger.log(resp)
}
And it gives me this log:
Why does it show my real IP?
What's going on under the hood? I expected the real IP with UrlFetchApp uses in .getRequests() output.
Am I missing something?
Are there any tricks of knowing which IP does UrlFetchApp use?
I know that there is no this functionality as a native function.
You can find a list of IP addresses that Apps Script may use while calling other services here - https://www.gstatic.com/ipranges/goog.txt
It's buried in this JDBC article.
Related
I wrote a web application on Google app script and it works, but for implementation I need to get an API key, to get it I need a white list of ip addresses, unfortunately the
UrlFetchApp.fetch
command has too wide a range of them.
I don't know how to solve this problem maybe you can use a proxy server?
Or if you now how i can use Google cloud for get static ip for my app csript or general static ip for app script
I have a Google Cloud Function. I also have a web application. I want to authenticate requests to the cloud function by using a service account.
I have the json key file.
I know that I have to follow https://cloud.google.com/functions/docs/securing/authenticating#service-to-function. But that is leading me to an IAP page that does not apply to google cloud functions.
Another similar instructions are found in https://developers.google.com/identity/protocols/oauth2/service-account
But if I am following the python library code, I end up with the sample code there :
import googleapiclient.discovery
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
response = sqladmin.instances().list(project='exciting-example-123').execute()
This does not directly relate to invoking a cloud function.
This question's answer somewhat deals with my requirement but is using a Call API which is only suitable for testing.
Also, I want to expose this API to multiple applications using another tech like .net. So I believe the best option for me will be to use the HTTP method (given on the same page):
https://developers.google.com/identity/protocols/oauth2/service-account#httprest
But whatever I do I am unable to get the signature right.
Any help to get this sorted will be highly appreciated as I am stuck on this for the past few days.
You can use the Google auth library like this
from google.oauth2.id_token import fetch_id_token
from google.auth.transport import requests
audience="my_audience"
r = requests.Request()
token=fetch_id_token(r,audience)
print(token)
The fetch_id_token method will use the default credentials
The service account key file defined in the environment variable GOOGLE_APPLICATION_CREDENTIALS
The service account loaded in the Google Cloud environment
For now, I followed this answer in PHP
In the claims section, I removed the scope. Instead added a claim of target_audience.
"target_audience" => "google-function-http-trigger"
the cloud function http trigger will look like https://us-central1-test-project-name.cloudfunctions.net/function-name",
This will give the required assertion key.
Then I follow https://developers.google.com/identity/protocols/oauth2/service-account#httprest to get the id_token
Then with the id_token as the bearer token we can call the cloud function.
please note that the token expires depending on the time set in the "exp" claim. Once expired you have to redo the steps to generate the new id_token
I want to authenticate requests to the cloud function by using a service account.
I am not sure I understand the context correctly, but I would try to assign a roles/cloudfunctions.invoker IAM role to that service account (which is used to run your code in the web application) - see Cloud Functions IAM Roles .
In that case a code under that service account "Can invoke an HTTP function using its public URL"
I reckon no json keys are required in this case.
I am developing an add-on for google drive.
As a part of the functionality of this add-on, I would like to incorporate a google vm server that performs some processing on a user's google drive files (i.e. you click on a file through the add-on, send a request with a download link to the server, the server downloads the file, then finally responds to the request with some helpful information about the file). Both the apps script for the add-on and the vm instance are connected to the same google "project."
I am struggling with google's OAuth2.0 system and how I can connect the authorization of the add-on and the vm instance together.
Currently, when users open the add-on for the first time, they are brought to the authorization screen like so .
Once they authorize, my add on has access to all the expected scopes, including read access to google drive files.
Now I want my server to have access to them as well. Unfortunately, I do not understand how to do this.
I have tried simply requesting the url returned from file.getDownloadUrl() in python. While the request returns a status code of 200, I cannot seem to get the file to download.
I have also looked into the Google Drive API for python (I am running a flask server). Unfortunately, it appears that I need an entirely new authorization flow to make it work.
Any clarity on this issue would be greatly appreciated. Frankly, I find google's documentation on this matter very scattered and confusing. So, even knowing the right place to look would extremely helpful.
Much Thanks!
EDIT
I am adding some additional code to help provide some clarity. This is currently how I make a request to my server from the add-on:
var route = http://exampleurl.com/process
var data = {
'oAuthToken': ScriptApp.getOAuthToken(),
'stateToken': ScriptApp.newStateToken().withTimeout(120).createToken(),
'fileId': e.parameters.fileId,
'fileType': e.parameters.fileMimeType
};
var options = {
'method' : 'post',
'payload' : data
};
var response = UrlFetchApp.fetch(route, options);
This code successfully sends information to my vm instance running my server.
Now, I need to authorize the server to download the file specified by fileId.
When developing, I closely followed this tutorial to set up OAuth2.0 access to the Drive API. Here are two key routes:
#app.route('/google/login')
#no_cache
def login():
session = OAuth2Session(CLIENT_ID, CLIENT_SECRET,
scope=AUTHORIZATION_SCOPE,
redirect_uri=AUTH_REDIRECT_URI)
uri, state = session.create_authorization_url(AUTHORIZATION_URL)
flask.session[AUTH_STATE_KEY] = state
flask.session.permanent = True
return flask.redirect(uri, code=302)
#app.route('/google/auth')
#no_cache
def google_auth_redirect():
req_state = flask.request.args.get('state', default=None, type=None)
if req_state != flask.session[AUTH_STATE_KEY]:
response = flask.make_response('Invalid state parameter', 401)
return response
session = OAuth2Session(CLIENT_ID, CLIENT_SECRET,
scope=AUTHORIZATION_SCOPE,
state=flask.session[AUTH_STATE_KEY],
redirect_uri=AUTH_REDIRECT_URI)
oauth2_tokens = session.fetch_access_token(
ACCESS_TOKEN_URI,
authorization_response=flask.request.url)
flask.session[AUTH_TOKEN_KEY] = oauth2_tokens
return flask.redirect(BASE_URI, code=302)
Is there a way to plug in the two tokens I generate from the add-on into this Oauth flow? It appears that Google isn't anticipating this setup given that I am required to provide a redirect URL, which wouldn't make much sense in the case of my add-on/server tech stack.
Currently, you can successfully send the access token from the Apps Script project (retrieved with getOAuthToken()), to the flask server.
Since you already got the access token, you don't need to go through all the OAuth process as defined here (use the application credentials to request the access token, provide user consent, redirect, etc.). Sending the access token through the API request is actually the last step in the OAuth flow.
You just need to use the token to build the service, and the server will be able to access the file.
Using access token to build service:
from googleapiclient.discovery import build
import google.oauth2.credentials
ACCESS_TOKEN = requestBody['oAuthToken'] # Data coming from Apps Script via UrlFetch
creds = google.oauth2.credentials.Credentials(ACCESS_TOKEN)
drive_service = build('drive', 'v3', credentials=creds) # Build Drive service
Using Drive service to download files:
After you've build the Drive service to access the API, you can use this code sample to download Google Documents, or this one for other files (both examples include a tab with a Python sample).
Note:
You might need to Install the Google Client Library if you haven't done so.
Reference:
Using OAuth 2.0 to Access Google APIs
I am playing with Google Script UrlFetchApp fetch and figured out, that the requests it makes are done from different IP addresses. If you call UrlFetchApp.fetch() multiple times, every request is made from another IP.
I am using DigestAuth and a SessionId to make my requests and I am getting 403 Forbidden because the call to get the SessionId (which is IP-based) is from a different IP.
f.e.
Call to get the SessionId was from 107.178.192.52
and the call which uses the IP-based SessionId was from 107.178.192.56
Can I force UrlFetchApp.fetch() to make the requests from the same IP?
No, it's not possible unfortunately.
The ranges of IPS used by google apps scripts however are available:
https://developers.google.com/apps-script/guides/jdbc
Check the section "Setup for other databases" on that page.
What are the public facing IP addresses, when app maker calls an external service with urlfetch?
My external service insists on white-listing these. Is there a public list available from google?
Within App Maker, I want to use the UrlFetch to call an external service, very much like the App maker sample.
I see there is a list of Apps Script's IP address ranges for the JDBC. Would this be the same ranges?
(https://developers.google.com/apps-script/guides/jdbc#accessing)
Thanks in advance,
John
Since App Maker uses Apps Script's URL Fetch service, you need to look at their doc to answer this question. From what I can tell from:
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
You need to go here:
https://cloud.google.com/appengine/kb/#static-ip
And then follow these instructions. Since Stack Overflow has an issue with simply posting links (although I really recommend you go to the link :), I'll summarize the instructions here:
nslookup -q=TXT _cloud-netblocks.googleusercontent.com 8.8.8.8
And then nslookup each "include" in the response. This gives you all the IPs currently in use.
Edit: It looks like this might be the same IPs Google uses for it's general URL fetch service, which could mean that if you're whitelisting for these IPs you may also whitelist for all App Engine applications, and probably even more. Obviously you'd be whitelisting for all Apps Script and App Maker applications, so I assume this doesn't matter, but I just wanted to mention it. If your service is trying to rely on this for security reasons then, obviously, it's not adequate.
I had the same issue,
may be you can try the "useIntranet" option which may reduce the ipaddress range within your websites/webapps current network
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
eg:
var response = UrlFetchApp.fetch("https://Url.com",{
'method' : 'post',
'payload' :{
'useIntranet':true,
'key':"value"
}
}
);