Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow connector to accept loginAuth to pass it down to sqlAdminFetcher #204

Closed
wants to merge 0 commits into from

Conversation

Anoupz
Copy link

@Anoupz Anoupz commented Sep 14, 2023

Change Description

Allow connector to accept custom auth as arg to be able to pass it down to sqlAdminFetcher which can rely on custom auth or default auth if none is provided.

Relevant issues:

@Anoupz Anoupz requested a review from a team as a code owner September 14, 2023 18:39
@conventional-commit-lint-gcf
Copy link

🤖 I detect that the PR title and the commit message differ and there's only one commit. To use the PR title for the commit history, you can use Github's automerge feature with squashing, or use automerge label. Good luck human!

-- conventional-commit-lint bot
https://conventionalcommits.org/

@Anoupz Anoupz changed the title feat: Allow connector to accept loginAuth as args to pass it down to sqlAdminFetcher feat: Allow connector to accept loginAuth to pass it down to sqlAdminFetcher Sep 14, 2023
@jackwotherspoon
Copy link
Collaborator

@Anoupz Thanks for the contribution! Would you mind maybe adding a quick test to https://github.com/GoogleCloudPlatform/cloud-sql-nodejs-connector/blob/main/test/connector.ts that covers passing in a credential?

@edosrecki
Copy link
Contributor

@Anoupz , @jackwotherspoon

What about the auth here:

const auth = new GoogleAuth({

@jackwotherspoon
Copy link
Collaborator

What about the auth here:

const auth = new GoogleAuth({

@Anoupz the way the Connector works is it has two credential Google Auth objects, each with different access scopes. The loginAuth is used for logging in with automatic IAM database authentication and has the 'https://www.googleapis.com/auth/sqlservice.login' scopes required to purely login to a Cloud SQL database. The second Google Auth object that @edosrecki is pointing out is used for authorization and to authorize the client used to make Cloud SQL Admin API calls (aka does the person connecting have the proper permissions to connect to Cloud SQL) and requires the 'https://www.googleapis.com/auth/sqlservice.admin'.

Both of these credentials must belong to the same IAM Principal in order to successfully connect with IAM database authentication. Thus, we need to support setting both of these to the custom credentials passed in.

In Python we can pass in a single credentials object because the google-auth library allows credentials to be re-scoped (hence we can pass in a single credentials object and scope it as required to satisfy both auth credentials). I wonder if something similar is possible for the node google-auth-library?

@Anoupz
Copy link
Author

Anoupz commented Sep 14, 2023

What about the auth here:

const auth = new GoogleAuth({

@Anoupz the way the Connector works is it has two credential Google Auth objects, each with different access scopes. The loginAuth is used for logging in with automatic IAM database authentication and has the 'https://www.googleapis.com/auth/sqlservice.login' scopes required to purely login to a Cloud SQL database. The second Google Auth object that @edosrecki is pointing out is used for authorization and to authorize the client used to make Cloud SQL Admin API calls (aka does the person connecting have the proper permissions to connect to Cloud SQL) and requires the 'https://www.googleapis.com/auth/sqlservice.admin'.

Both of these credentials must belong to the same IAM Principal in order to successfully connect with IAM database authentication. Thus, we need to support setting both of these to the custom credentials passed in.

In Python we can pass in a single credentials object because the google-auth library allows credentials to be re-scoped (hence we can pass in a single credentials object and scope it as required to satisfy both auth credentials). I wonder if something similar is possible for the node google-auth-library?

Humm, When I tested this I did not encounter any issue. Let me check again

@jackwotherspoon
Copy link
Collaborator

Humm, When I tested this I did not encounter any issue. Let me check again

@Anoupz are you using IAM database authentication to login for your use-case or regular username/password database auth?

@Anoupz
Copy link
Author

Anoupz commented Sep 14, 2023

Humm, When I tested this I did not encounter any issue. Let me check again

@Anoupz are you using IAM database authentication to login for your use-case or regular username/password database auth?

I am using IAM database authentication.

@Anoupz
Copy link
Author

Anoupz commented Sep 14, 2023

What about the auth here:

const auth = new GoogleAuth({

@Anoupz the way the Connector works is it has two credential Google Auth objects, each with different access scopes. The loginAuth is used for logging in with automatic IAM database authentication and has the 'https://www.googleapis.com/auth/sqlservice.login' scopes required to purely login to a Cloud SQL database. The second Google Auth object that @edosrecki is pointing out is used for authorization and to authorize the client used to make Cloud SQL Admin API calls (aka does the person connecting have the proper permissions to connect to Cloud SQL) and requires the 'https://www.googleapis.com/auth/sqlservice.admin'.
Both of these credentials must belong to the same IAM Principal in order to successfully connect with IAM database authentication. Thus, we need to support setting both of these to the custom credentials passed in.
In Python we can pass in a single credentials object because the google-auth library allows credentials to be re-scoped (hence we can pass in a single credentials object and scope it as required to satisfy both auth credentials). I wonder if something similar is possible for the node google-auth-library?

Humm, When I tested this I did not encounter any issue. Let me check again

Sorry, I was not able to reproduce it. Can anyone help me to update this and what should be updated with? I only pass the loginAuth since the getEphemeralCertificate function would be able to use the passed in loginAuth and get the access token and the client.

@enocom
Copy link
Member

enocom commented Sep 15, 2023

The PR here might be a good thing to build on: #210 and will make it easy to pass in an auth object.

@Anoupz
Copy link
Author

Anoupz commented Sep 15, 2023

The PR here might be a good thing to build on: #210 and will make it easy to pass in an auth object.

Thanks @enocom. @edosrecki you can combine these two changes or I can merge your changes on mine. Feel free to edit it.

@edosrecki
Copy link
Contributor

edosrecki commented Sep 18, 2023

@jackwotherspoon, @Anoupz, @ruyadorno

Can't we do the following:

constructor(options?: { authClient?: AuthClient }) {
  const adminAuth = new GoogleAuth({
    authClient: options.authClient,
    scopes: ['https://www.googleapis.com/auth/sqlservice.admin'],
  });
  const loginAuth = new GoogleAuth({
    authClient: options.authClient,
    scopes: ['https://www.googleapis.com/auth/sqlservice.login'],
  })
 
  // ...
}

If a custom AuthClient object is passed by the library user, GoogleAuth class will use it, otherwise it will set it up by doing it's own magic. This should be equivalent to Python library's with_scopes() call.

@enocom
Copy link
Member

enocom commented Sep 18, 2023

That looks good to me. @ruyadorno WDYT?

@edosrecki
Copy link
Contributor

edosrecki commented Sep 28, 2023

@jackwotherspoon @enocom @ruyadorno @Anoupz

I just tried out what I suggested above, and it does not work due to a TypeScript error.

Sqladmin constructor expects auth: GoogleAuth, which is a generic type GoogleAuth<T extends AuthClient = JSONClient>. As you can see it is defaulted to JSONClient which is a union type JSONClient = JWT | UserRefreshClient | BaseExternalAccountClient | ExternalAccountAuthorizedUserClient | Impersonated;.

Therefore we cannot pass just any AuthClient, but only those specified in JSONClient type. I believe this is a type mistake. I think that Sqladmin should be generic in T extends AuthClient, and should allow auth: GoogleAuth<T>.

I created an issue here: googleapis/google-api-nodejs-client#3357 to start the discussion.

@ruyadorno
Copy link
Contributor

ruyadorno commented Sep 29, 2023

@edosrecki @jackwotherspoon I also noticed that google-auth-library has a DownscopedClient that would be ideal to implement something similar to how it works on the Python Connector. Unfortunately it seems to use a CredentialAccessBoundary system that is only available on Cloud Storage for now.

Nevermind, @enocom clarified to me that's not even the same feature, it's just misleadingly sharing the same name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for specifying custom credentials
5 participants