- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
03-20-2023 08:26 AM - edited 03-20-2023 08:40 AM
Introduction
Google Cloud Platform, like AWS and Azure, is a significant cloud infrastructure service. We recently integrated GCP's BigQuery product as part of an implementation for user provisioning.
When using Service Accounts (the recommended server-to-server authentication method for these type of integrations), the provided client libraries by Google allow you to easily integrate and authenticate. However, within the Now Platform, it is not possible to use these libraries.
OAuth2 is used for GCP server-to-server authentication, but when using service accounts, it is not possible to use the clientside OAuth redirection flow. There is no client secret, only a certificate and a private key (which is not the same thing). Therefore, we can't use the built-in Now Platform OAuth2 authentication functionality.
As a result, we integrated GCP by calling the REST APIs, which requires signed JWT tokens. This article walks us through that process and gives an end-to-end description of how to accomplish the integration of GCP without the use of Google's client libraries.
Image credit: Google Developer Documentation
Obtaining an access token
In order to make REST calls to Google BigQuery or other GCP platforms, we need an access token. This token is retrieved from server-to-server OAuth using a service account, as described in this documentation: https://developers.google.com/identity/protocols/oauth2/service-account
Assuming that the service account file has been provided to you (obtaining it is out of scope for this article), we need to implement the steps that are described in this section, under the HTTP/REST tab.
The idea is that we will be able to create JWT tokens that are signed with the certificates embedded in the service account file. Fortunately, the platform provides part of this functionality out of the box, through X509 certificates, JWT keystores and JWT providers. We just need to set them up.
Creating the certificates, keystores and providers
First, follow the steps in this document in order to create a Java KeyStore certificate based on the security certificate sent by Google: Create a Java KeyStore certificate. After following this documentation, you should have passwords which you used to sign, an X509 cert .pem file and a .jks keystore.
Next, we create a new entry in the X.509 Certificates table (sys_certificate):
- Type = Java Keystore
- Keystore password = as created
- Add the generated .jks file as an attachment
Afterwards, we create a JWT Keys entry in the jwt_keystore_aliases table:
- Signing keystore = the record created in the previous step
- Signing algorithm = RSA 256
- Signing key = as created
Finally, we create a new JWT Provider:
- Signing Configuration = previously created JWT Keys record
- Standard claims:
-- Name = aud, Value = https://oauth2.googleapis.com/token
-- Name = iss, Value = service account "email address" ending in .gserviceaccount.com
Obtaining a token
At this point, we are able to sign our own JWT tokens that can use to call the OAuth token endpoint:
var scopes = [
'https://www.googleapis.com/auth/bigquery',
'https://www.googleapis.com/auth/cloud-platform'
];
var jwtAPI = new sn_auth.GlideJWTAPI();
var header = JSON.stringify({ });
var payload = JSON.stringify({ scope: scopes.join(" ") });
var jwtProviderSysId = gs.getProperty('gcp.jwt.provider.sysid');
var jwt = jwtAPI.generateJWT(jwtProviderSysId, header, payload);
gs.info(jwt);
I have decided to store the JWT Provider record's sys ID in a system property for easy reconfiguration.
Now we are able to create our signed JWTs, we just need to call the token endpoint on GCP and get a Bearer token. For that, I have created a new Outbound REST Message with endpoint = https://oauth2.googleapis.com/token called "Google Cloud Platform OAuth token".
I added a POST method call with No authentication, and 2 HTTP Query Parameters:
- Name = grant_type, Value = urn:ietf:params:oauth:grant-type:jwt-bearer
- Name = assertion, Value = ${jwt}
And finally we can make another function calling this REST message based on a jwt:
var jwt = createJwt(); // output of above snippet
var r = new sn_ws.RESTMessageV2('Google Cloud Platform OAuth token', 'Get token'); // name of your REST Message and request here
r.setStringParameterNoEscape('jwt', jwt);
var response = r.execute();
var responseBody = response.getBody();
var access_token = JSON.parse(responseBody).access_token;
gs.info(access_token);
We have obtained a successful Bearer token to be used in calls to GCP endpoints!
Querying Google BigQuery
At this time we can call any GCP endpoint using our access token. In our case, we will query the /bigquery/v2/projects/${projectId}/queries endpoint.
Thus, we make a new REST Message, calling "Google BigQuery query" with endpoint https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/queries.
Once again we set No authentication (we will authenticate through the header), and we create a new POST method call called "Query". Here, we set the HTTP request as follows:
Headers:
- Name = Accept, Value = application/json
- Name = Authorization, Value = Bearer ${accessToken}
- Name = Content-Type, Value = application/json
And finally, our code:
var token = createAuthToken(); // output from the previous call
var projectId = 'YOUR-GBQ-PROJECT-ID';
var bodyObj = { "query": query };
var r = new sn_ws.RESTMessageV2('Google BigQuery query', 'Query');
r.setStringParameterNoEscape('accessToken', token);
r.setStringParameterNoEscape('projectId', projectId);
r.setRequestBody(JSON.stringify(bodyObj));
var response = r.execute();
var responseBody = response.getBody();
gs.info(responseBody);
Conclusion
In conclusion, we were able to connect to Google Cloud Platform without the Google client libraries by manually constructing and encrypting a JWT token and sending that to the OAuth endpoint, to retrieve a Bearer token.
We can then use the Bearer token to make any endpoint call within GCP, such as to GBQ's queries endpoint. However, this token can be used to authorize any other endpoint call, if the service account's scopes allow.
- 7,095 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi folks. I've followed all steps and I successful retrieve both JWT and Token. Unfortunately when I use the token to connect my specific end-point on GPC, I see in the logs:
Integration crypto failure protocol=HTTPS javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated callchain=[{http '2023-08-30T08:43:21.849866Z' '9'}, {sys_ui_action '48c17ed207131000dada43c0d1021e83' 'global' '48c17ed207131000dada43c0d1021e83' '2023-08-30T08:43:21.840825Z' '8' '8'}]
and using the token directly on the REST UI: Request not sent to uri= https://XX.YY.it/ : org.apache.commons.httpclient.HttpException: Session contains no certificates - Untrusted

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I think the error is due to this article:
https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB1112530
The KB contains an invalid link: so in order to enable roles about KMF you have to see here: https://docs.servicenow.com/bundle/sandiego-platform-security/page/administer/key-management-framewo...
I've found "Module Access Policy" giving to my admin on my istance both KMF admin and KMF cryptographic manager roles..... First the KMF admin + logout, after KMF cryptographic manager + logut ... and finally the module was there!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi folks,
unfortunately also enabling the KMF on my personal istance the connection with my GCP endpoint still fails and into logs I see:
Integration crypto failure protocol=HTTPS javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated callchain=[{http '2023-08-30T13:56:48.385475Z' '11'}, {scoped_script_evaluation 'e37ada1c474531109289b616536d43b2' 'script' '2023-08-30T13:56:48.296148Z' '8'}]
Iv'e also opened a specific case to understand where is the point (CS6859348) and I've also tried to follow this KB: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB1509991
Again I find that the steps given are unclear ... So I wait for exiting from this "dead-end road"
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @Xander H,
I tried to implement the same integration with a single script include. It worked fine. Please let me know if there are any mistakes or best practices I need to follow.
Please review my code in GitHub repo and below is link to my GitHub
https://github.com/thangarajmohan/GCP-BigQuery-to-ServiceNow/tree/main
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @gandalf, looks like the issues you are seeing are related to a local (on-premise) installation and SSL configuration. Afraid that's beyond the area of my expertise and hope Now Support will be able to help you!
@Mohan raj indeed, your single script include looks like it contains all the functionality. From a scripting best practice, it's recommended to break up the function `getData` in some smaller function units (for reusability, maintainability, testability, etc).
I would also store the REST Message templates in a record (less code, easier to manage) as per the article, and it's generally not a great idea to hardcode sys IDs (like that of the JWT provider), they should be stored in system properties.
Finally, I don't think you want to include an "exp" key in the payload for creating the JWT - it means "expiration" and will be dynamically generated. I think it is being overridden in your case so there's no real harm in having it per se, just extraneous and possibly confusing moving forward (in a few months time you will think - why was it there?).
With all that said, these are all best practices - your core functionality seems to work fine, good work!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi gents
I share the end of story.
- The first error (Integration crypto failure protocol=HTTPS) - I'm not sure about it - but it's been solved by installing a x509 certificate (PEM format) on the sys_certificate table. The PEM file has given to me directly by Google team.
- Installed the PEM certificate related to the endpoint, I've obtained another error (No issuer certificate found for ....) Here the article useful to solve it --> https://www.servicenow.com/community/developer-forum/receiving-no-issuer-certificate-found-for-error...
Really useful to test the chain autority this link, reported on the above link --> https://www.digicert.com/help/
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi,
I have a question regarding the CMDB class used to identify Bigquery data. Do you have any idea ?
Thank you
Ali S.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Ali,
I'm not entirely sure what your question concretely is. However we did not integrate this data with CMDB as our BigQuery data was used for sys_user creation and nothing relating to CMDB.