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

RDS IAM Authentication Token Generator #1157

Closed
pula2000 opened this issue Mar 21, 2019 · 19 comments
Closed

RDS IAM Authentication Token Generator #1157

pula2000 opened this issue Mar 21, 2019 · 19 comments
Labels
feature-request A feature should be added or improved.

Comments

@pula2000
Copy link

pula2000 commented Mar 21, 2019

I'm trying to use V2 SDK for RDS to establish a JDBC connection to an RDS instance using IAM DB authentication. But the example in the tutorial uses the auth package in the V1 sdk. I don't see an equivalent package in the V2 RDS module. Would be great if someone could point me to the right place in V2 for doing the same. Thanks

@varunnvs92
Copy link
Contributor

V2 auth module link: https://github.com/aws/aws-sdk-java-v2/tree/master/core/auth
Can you give a link to the tutorial?

@zoewangg
Copy link
Contributor

zoewangg commented Apr 2, 2019

Closing this due to inactivity. Feel free to reopen if you have further questions.

@zoewangg zoewangg closed this as completed Apr 2, 2019
@justnance justnance added guidance Question that needs advice or information. and removed Question labels Apr 19, 2019
@abatkin
Copy link

abatkin commented Jun 20, 2019

@zoewangg This issue is clearly not solved (and auto-closing after 12 days isn't very friendly) - can you reopen and assign to the right place please?

In order to connect to an RDS instance that is using IAM auth, you need to generate an auth token (the cli provides aws rds generate-db-auth-token for this purpose). AWS provides documentation for the v1 Java SDK, but I can't find any corresponding documentation for the v2 Java SDK.

Actually I don't see any parallel classes in the v2 Java SDK, which means that either they are hidden/undocumented somewhere (hence this ticket!) or else it isn't implemented (in which case we need a different ticket to ask for that to be implemented).

At this point the only option appears to be translating the v1 docs for manually generating a token ("Manually Constructing an IAM Authentication Token" in the docs linked above) which is very cumbersome.

@zoewangg
Copy link
Contributor

As a general rule, we try to close an issue if there is no response from customers after 7 days to make sure we are on top of all issues; the issue list will grow uncontrollably if we leave all unresponsive issues open. You are always welcome to create new issues or comment on any issues. That said, thank you for your feedback and we might consider increasing auto-closing period.

Now that we have more information on this issue, we will take another look.

@zoewangg zoewangg reopened this Jun 20, 2019
@forficate
Copy link

Adding my +1 vote.

This is a crucial piece of functionality missing from the new SDK.

@millems
Copy link
Contributor

millems commented Jun 24, 2019

Transitioning to a feature request: "Support RdsIamAuthTokenGenerator equivalent in V2 of the Java SDK." This will be prioritized against other high-level libraries, but this doesn't look like a ton of effort to implement. It seems like there's a lot of overlap with the presigners task: #849

@millems millems added feature-request A feature should be added or improved. and removed guidance Question that needs advice or information. labels Jun 24, 2019
@millems millems changed the title Use auth package in RDS module Support RdsIamAuthTokenGenerator equivalent in V2 of the Java SDK Jun 24, 2019
@millems millems changed the title Support RdsIamAuthTokenGenerator equivalent in V2 of the Java SDK RDS IAM Authentication Token Generator Jul 8, 2019
@jeffzoch
Copy link

jeffzoch commented Oct 1, 2019

Would really love to see any documentation on doing this in v2. The manual construction is quite cumbersome and error prone and this would make a lot of sense.

@rosscdh
Copy link

rosscdh commented Oct 25, 2019

+1 seems to be quite a popular and used function

@solvip
Copy link

solvip commented Dec 4, 2019

We worked around the lack of this, inspired by #868 and https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-rds/src/main/java/com/amazonaws/services/rds/auth/RdsIamAuthTokenGenerator.java

package foo

import java.time.Instant

import software.amazon.awssdk.auth.credentials.AwsCredentials
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
import software.amazon.awssdk.auth.signer.params.Aws4PresignerParams
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.auth.signer.Aws4Signer
import software.amazon.awssdk.http.SdkHttpFullRequest
import software.amazon.awssdk.http.SdkHttpMethod

import scala.concurrent.ExecutionContext
import scala.concurrent.Future

class RDSClient(implicit ec: ExecutionContext) {

  // We only support eu-west-1 for now.  Move this out into a constructor param
  // if you need a different region.
  protected val region: Region = Region.EU_WEST_1

  /**
    * Create an authentication token for an RDS database
    * @param hostname hostname of the rds database
    * @param port port of the rds database
    * @param username username to authenticate as
    * @return Future of a temporary database password
    */
  def getAuthToken(hostname: String, port: Int, username: String): Future[String] =
    resolveDefaultCredentials.map({ credentials =>
      val params = Aws4PresignerParams
        .builder()
        .expirationTime(Instant.now.plusSeconds(15 * 60))
        .awsCredentials(credentials)
        .signingName("rds-db")
        .signingRegion(region)
        .build()

      val request = SdkHttpFullRequest
        .builder()
        .encodedPath("/")
        .host(hostname)
        .port(port)
        .protocol("http") // Will be stripped off; but we need to satisfy SdkHttpFullRequest
        .method(SdkHttpMethod.GET)
        .appendRawQueryParameter("Action", "connect")
        .appendRawQueryParameter("DBUser", username)
        .build()

      Aws4Signer.create().presign(request, params).getUri.toString.stripPrefix("http://")
    })

  // Resolve the default credentials.  We wrap it in a Future, because the underlying call might result
  // in calls to AWS sts services, metadata services, etc and return god knows when.
  protected def resolveDefaultCredentials: Future[AwsCredentials] = Future {
    DefaultCredentialsProvider.create.resolveCredentials()
  }
}

@solvip
Copy link

solvip commented Dec 4, 2019

I'd be happy to convert the above into a PR if you could tell me where you wanted the function to live. :)

@millems
Copy link
Contributor

millems commented Dec 4, 2019

@solvip Thanks for the code! We've gotten a lot of feedback on 1.11.x that it's hard to find functionality like this. If you create a PR, maybe some renames would make it easier to find it?

S3 is our most fleshed-out service in V2 so far, so we can look to it for how we've handled discoverability so far. We have S3Utilities and S3Presigner.

This actually seems closer to S3Utilities than S3Presigner, since it's not presigning a request. It's generating a URL that happens to be presigned, similar to how S3Utilities generates a URL.

What do you think about creating a RDSUtilities that starts as a copy+paste of the S3Utilties pattern for this functionality?

@solvip
Copy link

solvip commented Dec 4, 2019

@millems I actually expected to find this as part of the software.amazon.awssdk.services.rds. RdsAsyncClient / software.amazon.awssdk.services.rds.RdsClient. Probably due to AWS CLI having this as aws rds generate-db-auth-token

RDSUtilities is fine if there's precedence for it in S3. I'll open a PR, thanks!

@millems
Copy link
Contributor

millems commented Dec 4, 2019

We've actually talked about having an Rds entry point for everything RDS related. Something like:

RdsClient client = Rds.client();
RdsAsyncClient asyncClient = Rds.asyncClient();
RdsClient client = Rds.clientBuilder().build();
RdsAsyncClient asyncClient = Rds.asyncClientBuilder().build();
RdsUtilities utilities = Rds.utilities();
RdsUtilities utilities = Rds.utilitiesBuilder().build();

@janlisse
Copy link

janlisse commented Jan 8, 2020

Any progress on this?

@abatkin
Copy link

abatkin commented Feb 19, 2020

@millems I'm not sure if it would make sense to put this into the generic Rds client. Most of the RDS API functionality is "control plane" activity, whereas generating a password is more of a "data plane" activity (it's not actively accessing the database, but it's a prerequisite for doing that and only that). Most applications likely either access the RDS control plane XOR data plane.

@uherberg
Copy link

uherberg commented May 1, 2020

Any updates on this? This would be a very useful feature

@millems
Copy link
Contributor

millems commented May 4, 2020

Sorry, no updates at this time. Please +1 the root issue to express support for it. That helps us with prioritization.

@debora-ito
Copy link
Member

Feature added via #2057, released in SDK version 2.16.3.

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved.
Projects
None yet
Development

No branches or pull requests