Jdbc connection error from Google Apps Script - jdbc

I have created a Google Cloud Project MySQL database to use in conjunction with the Jdbc service provided by Google Apps Script. Everything went as planned with the connection. I am basically connecting as it does in the docs.
var conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
I shared the file with another account and all of a sudden I am seeing a red error saying:
'Failed to establish a database connection. Check connection string, username and password.'
Nothing changed in the code, but there is an error. When I go back to my original account and run the same bit of code, there is no error. What is happening here? Any ideas?

Jdbc.getConnection works from both: my account and another account:
var conn = Jdbc.getConnection('jdbc:mysql://' + IP + ':3306/' + database_name, user, password)
I'm really confused because the recommended method did not work.
There are two ways of establishing a connection with a Google Cloud
SQL database using Apps Script's JDBC service:
(Recommended) Connecting using Jdbc.getCloudSqlConnection(url)
Connecting using Jdbc.getConnection(url)
Notes:
IP is a Public IP address from the OVERVIEW tab in your database console:
I've allowed any host when created a user:

I am not sure whether this question has been resolved or not, but let me add this answer.
I also faced the same problem but I found the resolution. What I did is:
First, go to the console.
https://console.cloud.google.com
Then, open IAM.
and add the account as a member and add this permission: "Cloud SQL Client".

I think this is a permission issue in your second account. Necessary information are missing in your question. But, the secound account, if run as a another user, won't necessarily have your sqlservice authorization. The permission,
https://www.googleapis.com/auth/sqlservice
Manage the data in your Google SQL Service instances
is required to use Jdbc.getCloudSqlConnection(url), while Jdbc#getConnectionUrl() just requires external link connection permission
https://www.googleapis.com/auth/script.external_request
I believe that you can only connect to sql instances owned by you with getCloudSqlConnection() which doesn't even require external connection permission. This method probably calls your sql instance internally.
References:
Jdbc#getCloudConnection
Jdbc#getConnection
Conclusion
To connect to any external service, you need external_request permission. But, You don't need that permission to connect to your own documents say, Spreadsheets owned by you/have edit access permission - through SpreadsheetApp.openByUrl(). I believe it's the same thing with Jdbc.getCloudSqlConnection(). It calls your Google sql internally - So, even if you grant external request permission, It won't work. What will work for this method is
Installable triggers (which runs as you).
Add the second account also as owner in GCP-IAM (may not work though) See this answer

I'd double-check once again all IP ranges which should be whitelisted. According to your description it worked fine in first account, probably in second account Apps Script uses another IP for connection, which was not whitelisted or whitelisted with some typo. Could you share screenshot how did you exactly whitelist the ranges from this article?

I have a GAS Add-On that uses a Google cloud dB. I initially set this up by:
Whitelisting Google Cloud IP ranges in my SQL instance
Getting the script.external_request scope approved for OAuth Consent screen
This all works great from GAS for the add-on, but I suspect that if this whitelist is not comprehensive and volatile (which I expect it is), I will see intermittent connectivity issues.
I recently added a Firebase web app that needs access to the same dB. I had issues, because Firebase does not conform to those Google IP ranges and does not expose its IP for whitelisting. So I had to create a socket layer connection as if Firebase was an external service.
Which got me thinking, should I put a socket layer in my GAS Add-On? But nothing in the GAS JBDC Class documentation indicates a socket parameter.
Which leads me to a question that was not really answered in this thread:
Does anyone know why Jdbc.getCloudSqlConnection(url) is the "Recommended" approach? The documentation seems to imply that because the IP whitelisting is not required, Jdbc.getCloudSqlConnection(url) is using a socket (or some other secure method) to connect to the dB?
It also seems silly that if that is the case, that I would need two have two sensitive scopes to manage a dB connection. I would rather not go through another OAuth const audit and require my users to accept another scope unless there is a benefit to doing so.

Related

Authenticating External System Connections to Web API with Azure AD

I'm trying to figure out how to migrate a system that is currently using ACS to Azure AD. I've read the migration docs provided by Azure and have looked through the Azure AD docs and the sample code but I'm still a bit lost as to what the best approach for my situation would be.
I've got a web API that has about 100 separate external systems that connect to it on a regular basis. We add a new connections approximately once a week. These external systems are not users--these are applications that are integrated with my application via my web API.
Currently each external system has an ACS service identity / password which they use to obtain a token which we then use to authenticate. Obviously this system is going away as of November 7.
All of the Azure AD documentation I've read so far indicates that, when I migrate, I should set up each of my existing clients as an "application registration" in Azure AD. The upshot of this is that each client, instead of connecting to me using a username and password, will have to connect using an application ID (which is always a GUID), an encrypted password, and a "resource" which seems to be the same as an audience URL from what I can see. This in itself is cumbersome but not that bad.
Then, implementing the authorization piece in my web API is deceptively simple. It looks like, fundamentally, all I need to do is include the properly configured [Authorize] attribute in my ApiController. But the trick is in getting it to be properly configured.
From what I can see in all the examples out there, I need to hard-code the unique Audience URL for every single client that might possibly connect to my API into my startup code somewhere, and that really does not seem reasonable to me so I can only assume that I must be missing something. Do I really need to recompile my code and do a new deployment every time a new external system wants to connect to my API?
Can anyone out there provide a bit of guidance?
Thanks.
You have misunderstood how the audience URI works.
It is not your client's URI, it is your API's URI.
When the clients request a token using Client Credentials flow (client id + secret), they all must use your API's App ID URI as the resource.
That will then be the audience in the token.
Your API only needs to check the token contains its App ID URI as the audience.
Though I want to also mention that if you want to do this a step better, you should define at least one application permission in your API's manifest. You can check my article on adding permissions.
Then your API should also check that the access token contains something like:
"roles": [
"your-permission-value"
]
It makes the security a bit better since any client app with an id + secret can get an access token for any API in that Azure AD tenant.
But with application permissions, you can require that a permission must be explicitly assigned for a client to be able to call your API.
It would make the migration a tad more cumbersome of course, since you'd have to require this app permission + grant it to all of the clients.
All of that can be automated with PowerShell though.

Can't authenticate to YouTube Data API anymore

We have two sites setup using the same API Key for uploading videos, one is the public server, another is on my local machine.
Even though they both use exactly the same credentials, the one on the public server is not working anymore (we're using https://github.com/laplacesdemon/django-youtube), throwing an error that credentials are incorrect.
Weirdly, I don't know where can be the problem.
There was one thing on our server, though, we changed the location so the IP address has changed.
Might it be this?
The IP list on the Server Key settings on Google Console is empty, and on the APIs requests graph I can see requests but can't find any log associated with them or something like this to see what's wrong.
Anyway, I guess the access is somehow blocked and there is no way to unblock it.
If anyone experiencing same issue, just create a new YouTube account! The only way of solving it, apparently.

Creating an android studio project to run queries on a google cloud sql server using jdbc driver

I have an cloud sql instance up and running and have made a link using a jdbc driver to the instance ip using android studio project. I can successfully run queries from an ip address that I insert manually into the google cloud sql settings and not any other network. This makes my app accessible only from certain ip addresses. Is there a way i can authenticate my google cloud sql to all ip addresses. I do not wish to use the google app engine if possible as I believe it will only complicate my application. My app works well enough is there an easy way to access my sql from any network having supplied my username and password in the code itself?
You can use the console to authorize 0.0.0.0, which will allow connections from any IP address. However, this is not necessarily a good solution. If you embed your database's username and password in your Android app, it can be found by someone else taking apart the apk. If they do that, they will then have complete access to your database. It is more complicated, but you should put some kind of server in front of your database, and have the user authenticate with that server/application, and only have that server communicate directly with your database.

Logging into oracle db as a global user

We are trying to shape up an old, 2 tier, Delphi based application. It originally uses database authentication, we'd like to transform the db user accounts to global users, so an OID server could perform the authentication instead of the database.
The Delphi program can no longer log into the database if the account is a global user. I'm trying to understand the login protocol, so far without results.
Similar thing happens with SQLDeveloper, I can't connect as a global user. SQLPlus however works with both kinds of users. We checked the information flow with Wireshark. When the dbserver asks back for a password, the SQLPlus sends it, while the SQLDeveloper doesn't send a password when attempting to connect as a global user.
The client sends the application name too in the login request. Is it possible that we have to store the client app name in the LDAP itself?
To connect to Oracle using OID, application must properly configure OCI (Oracle Call Interface). The data access components (which one ?), you are using, must set OCI_ATTR_DISTINGUISHED_NAME session attribute. If that is not done, then you will be not able to connect to Oracle server using ODI and OCI.
You should check your components documentation for this feature. And if it is not implemented, then discuss this issue with the components vendor. Actually, there is not much work to implement, but some work to setup testing environment is required ...

What is the best way to restrict access to a development website?

I have a site i am working on that i would like to display only to a few others for now. Is there anything wrong with setting up windows user names and using windows auth to prompt the user before getting into the development site?
There are several ways, with varying degrees of security:
Don't put it on the internet - put it on a private network, and use a VPN to access it
Restrict access with HTTP authentication (as you suggest). The downside to this is it can interfere with the actual site, if you are using HTTP auth, or some other type of authentication as part of the application.
Restrict access based on remote IP. Just allow the IPs of users you want to be able to access it.
Use a custom hostname. Have it on a public IP, but don't publish the hostname. This means make an entry in your HOSTS file (or configure your own DNS server, if possible) so that "blah.mysite.com" goes to the site, but that is not available on the internet. Obviously you'd only make the site accessible when using that hostname (and not the IP).
That depends on what you mean by "best": for example, do you mean "easiest" or "most secure"?
The best way might be to have it on a private network, which you attach to via VPN.
I do this frequently. I use Hamachi to allow them to access my dev box so they can see whats going on. they have access to it when they want , and/or when I allow. When they are done I evict them from my Hamachi network and change the password.
Hamachi is a software VPN. Heres a link to Hamachi - AKA LogMeIn
Hamachi
They have a free version which works quite well.
Of course, there's nothing wrong with Windows auth. There are couple of (not too big) drawbacks, though:
your website auth scheme is different from the final product.
you are giving them more access to the box they really need.
you automatically reimaging the machine and redeploying the website is more complex, as you have to automate the windows account creation.
I would suggest two alternatives:
to do whatever auth you plan on doing in the final website and make sure all pager require auth
do a token cookie based auth - send them a link that sets a particular token in a cookie and in your website code add quick check for that token before you even go to the regular user auth
If you aren't married to IIS, and you need developers to be able to change the content, I would consider Apache + SSL + WebDav (aka Web Folders). This will allow you to offer a secure sandbox where developers can change and view the content without having user accounts on the server.
This setup requires some knowledge of Apache so it only makes sense if you are already using Apache or if you frequently need to provide outsiders access to your web server.
First useful link I found on the topic: http://pascal.thivent.name/2007/08/howto-setup-apache-224-webdav-under.html
Why don't you just set up an NTFS user and assign it to the website (and remove anonymous access)

Resources