-
Notifications
You must be signed in to change notification settings - Fork 79
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: Auth token generator for AWS DSQL #1857
Conversation
…tRuntime to generate token for DSQL. Update comments to account for both RDS and DSQL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments to help reviews
@@ -0,0 +1,77 @@ | |||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the generated auth token generator for DSQL service. Included for reference.
@@ -0,0 +1,94 @@ | |||
package software.amazon.smithy.aws.swift.codegen.customization.dsql |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the codegen integration for generating auth token generator for DSQL.
@@ -68,7 +68,7 @@ class AuthTokenGeneratorIntegration : SwiftIntegration { | |||
username: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifies codegen integration for RDS auth token generation to use modified function name in runtime auth token generator
@@ -52,7 +52,7 @@ public class AuthTokenGenerator { | |||
username: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the generated diff for RDS auth token generator
@@ -16,7 +16,7 @@ import SmithyIdentity | |||
import struct Foundation.Date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is the underlying auth token generator in runtime library, used by RDS and DSQL service auth token generators.
val authTokenGeneratorWrapperClass = """ | ||
@_spi(AuthTokenGenerator) import class AWSClientRuntime.AuthTokenGenerator | ||
import SmithyIdentity | ||
import struct Foundation.TimeInterval | ||
|
||
/// A utility class with methods that generate IAM authentication token used for connecting to DSQL. | ||
public class AuthTokenGenerator { | ||
private let generator: AWSClientRuntime.AuthTokenGenerator | ||
|
||
/// The initializer that takes in AWSCredentialIdentity struct to use to generate the IAM authentication token. | ||
public init(awsCredentialIdentity: AWSCredentialIdentity) { | ||
self.generator = AWSClientRuntime.AuthTokenGenerator(awsCredentialIdentity: awsCredentialIdentity) | ||
} | ||
|
||
/// The initializer that takes in a specific AWSCredentialIdentityResolver, used to resolve the AWSCredentialIdentity used to generate the IAM authentication token. | ||
public init(awsCredentialIdentityResolver: any AWSCredentialIdentityResolver) async throws { | ||
self.generator = try await AWSClientRuntime.AuthTokenGenerator(awsCredentialIdentityResolver: awsCredentialIdentityResolver) | ||
} | ||
|
||
/// Updates the AWS credentials used to generate the IAM auth token. | ||
public func updateCredentials(newAWSCredentialIdentity: AWSCredentialIdentity) { | ||
generator.updateCredentials(newAWSCredentialIdentity: newAWSCredentialIdentity) | ||
} | ||
|
||
/// Updates the AWS credentials used to generate the IAM auth token by resolving credentials from passed in resolver. | ||
public func updateCredentials(awsCredentialIdentityResolver: any AWSCredentialIdentityResolver) async throws { | ||
try await generator.updateCredentials(awsCredentialIdentityResolver: awsCredentialIdentityResolver) | ||
} | ||
|
||
/// Generates authenetication token for non-admin connection using given inputs to the method and credential identity instance variable. | ||
/// | ||
/// - Parameters: | ||
/// - endpoint: The endpoint of the RDS instance. E.g., `peccy.dsql.us-east-1.on.aws` | ||
/// - region: The region that RDS instance is located in. E.g., `us-east-1` | ||
/// - expiration: The expiration for the token in seconds. Default is 900 seconds (15 minutes). | ||
public func generateDBConnectAuthToken( | ||
endpoint: String, | ||
region: String, | ||
expiration: TimeInterval = 900 | ||
) async throws -> String { | ||
return try await generator.generateDSQLAuthToken( | ||
endpoint: endpoint, | ||
region: region, | ||
expiration: expiration, | ||
isForAdmin: false | ||
) | ||
} | ||
|
||
/// Generates authenetication token for admin connection using given inputs to the method and credential identity instance variable. | ||
/// | ||
/// - Parameters: | ||
/// - endpoint: The endpoint of the RDS instance. E.g., `peccy.dsql.us-east-1.on.aws` | ||
/// - region: The region that RDS instance is located in. E.g., `us-east-1` | ||
/// - expiration: The expiration for the token in seconds. Default is 900 seconds (15 minutes). | ||
public func generateDBConnectAdminAuthToken( | ||
endpoint: String, | ||
region: String, | ||
expiration: TimeInterval = 900 | ||
) async throws -> String { | ||
return try await generator.generateDSQLAuthToken( | ||
endpoint: endpoint, | ||
region: region, | ||
expiration: expiration, | ||
isForAdmin: true | ||
) | ||
} | ||
} | ||
""".trimIndent() | ||
writer.write(authTokenGeneratorWrapperClass) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this... ideally we would generate as little as possible. But since we already do it like this for the RDS token we can take up a refactor if one is possible later on
|
||
// Remove https:// from the presigned URL to get final value for RDS auth token. | ||
let startIndex = presignedURL.absoluteString.index(presignedURL.absoluteString.startIndex, offsetBy: 8) | ||
let rdsAuthToken = String(presignedURL.absoluteString[startIndex...]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: dsqlToken*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
) | ||
|
||
guard let presignedURL = signedRequest?.destination.url else { | ||
throw ClientError.authError("Failed to generate auth token for RDS.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
token for DSQL*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
/// | ||
/// - Parameters: | ||
/// - endpoint: The endpoint of the RDS instance. E.g., `rdsmysql.123456789012.us-west-2.rds.amazonaws.com` | ||
/// - port: The port of the RDS instance to connect to. E.g., `3306` | ||
/// - region: The region that RDS instance is located in. E.g., `us-west-2` | ||
/// - username: The username of the RDS database user. E.g., `admin` | ||
/// - expiration: The expiration for the token in seconds. Default is 900 seconds (15 minutes). | ||
public func generateAuthToken( | ||
public func generateRDSAuthToken( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please check if its backward compatible, does it breaks any existing client using it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the underlying generator hidden from normal import unless user explicitly uses @_spi(AuthTokenGenerator)
tag to import it. Users of DSQL and RDS would use the auth token generator exposed via the wrapper in respective service modules, so this function name change isn't visible to them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean to say for clients it is impossible to import this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is part of AWSClientRuntime
module, and it's hidden unless users do @_spi(AuthTokenGenerator) import AWSClientRuntime
. A normal import import AWSClientRuntime
won't expose this function.
Instead of accessing the underlying generator, users can just use the wrapper generators. The respective service modules AWSRDS
and AWSDSQL
will have a wrapper for this hidden generator, which isn't hidden. You can see this code generation in GitHub diff of this PR. So users can simply do this:
import AWSDSQL
let token = AWSDSQL.AuthTokenGenerator(. . .).generateDBConnectAuthToken(. . .)
/// | ||
/// - Parameters: | ||
/// - endpoint: The endpoint of the RDS instance. E.g., `peccy.dsql.us-east-1.on.aws` | ||
/// - region: The region that RDS instance is located in. E.g., `us-east-1` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dsql*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
Issue #
2297
Description of changes
New/existing dependencies impact assessment, if applicable
Conventional Commits
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.