-
Notifications
You must be signed in to change notification settings - Fork 467
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#367] Enhanced multi-lang
AWSCredentialsProvider=...
decoder and c…
…onstruction. + added support for external ids (issue #367) + added support for endpoint+region (e.g., STS via VPC)
- Loading branch information
Showing
11 changed files
with
520 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
...s-client-multilang/src/main/java/software/amazon/kinesis/multilang/NestedPropertyKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright 2023 Amazon.com, Inc. or its affiliates. | ||
* Licensed under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package software.amazon.kinesis.multilang; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import com.google.common.base.CaseFormat; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* Key-Value pairs which may be nested in, and extracted from, a property value | ||
* in a Java properties file. For example, given the line in a property file of | ||
* {@code my_key = my_value|foo=bar} and a delimiter split on {@code |} (pipe), | ||
* the value {@code my_value|foo=bar} would have a nested key of {@code foo} | ||
* and its corresponding value is {@code bar}. | ||
* <br/><br/> | ||
* The order of nested properties does not matter, and these properties are optional. | ||
* Customers may choose to provide, in any order, zero-or-more nested properties. | ||
* <br/><br/> | ||
* Duplicate keys are not supported, and may result in a last-write-wins outcome. | ||
*/ | ||
@Slf4j | ||
public enum NestedPropertyKey { | ||
|
||
/** | ||
* Specify the service endpoint where requests will be submitted. | ||
* This property's value must be in the following format: | ||
* <pre> | ||
* ENDPOINT ::= SERVICE_ENDPOINT "^" SIGNING_REGION | ||
* SERVICE_ENDPOINT ::= URL | ||
* SIGNING_REGION ::= AWS_REGION | ||
* </pre> | ||
* | ||
* @see <a href="https://docs.aws.amazon.com/general/latest/gr/rande.html">AWS Service endpoints</a> | ||
* @see <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-regions">Available Regions</a> | ||
*/ | ||
ENDPOINT { | ||
void visit(final NestedPropertyProcessor processor, final String endpoint) { | ||
final String[] tokens = endpoint.split("\\^"); | ||
if (tokens.length != 2) { | ||
throw new IllegalArgumentException("Invalid " + name() + ": " + endpoint); | ||
} | ||
processor.acceptEndpoint(tokens[0], tokens[1]); | ||
} | ||
}, | ||
|
||
/** | ||
* External ids may be used when delegating access in a multi-tenant | ||
* environment, or to third parties. | ||
* | ||
* @see <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html"> | ||
* How to use an external ID when granting access to your AWS resources to a third party</a> | ||
*/ | ||
EXTERNAL_ID { | ||
void visit(final NestedPropertyProcessor processor, final String externalId) { | ||
processor.acceptExternalId(externalId); | ||
} | ||
}, | ||
|
||
; | ||
|
||
/** | ||
* Nested key within the property value. For example, a nested key-value | ||
* of {@code foo=bar} has a nested key of {@code foo}. | ||
*/ | ||
@Getter(AccessLevel.PACKAGE) | ||
private final String nestedKey; | ||
|
||
NestedPropertyKey() { | ||
// convert the enum from UPPER_SNAKE_CASE to lowerCamelCase | ||
nestedKey = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); | ||
} | ||
|
||
abstract void visit(NestedPropertyProcessor processor, String value); | ||
|
||
/** | ||
* Parses any number of parameters. Each nested property will prompt a | ||
* visit to the {@code processor}. | ||
* | ||
* @param processor processor to be invoked for every nested property | ||
* @param params parameters to check for a nested property key | ||
*/ | ||
public static void parse(final NestedPropertyProcessor processor, final String... params) { | ||
// Construct a disposable cache to keep this O(n). Since parsing is | ||
// usually one-and-done, it's wasteful to maintain this cache in perpetuity. | ||
final Map<String, NestedPropertyKey> cachedKeys = new HashMap<>(); | ||
for (final NestedPropertyKey npk : values()) { | ||
cachedKeys.put(npk.getNestedKey(), npk); | ||
} | ||
|
||
for (final String param : params) { | ||
if (param != null) { | ||
final String[] tokens = param.split("="); | ||
if (tokens.length == 2) { | ||
final NestedPropertyKey npk = cachedKeys.get(tokens[0]); | ||
if (npk != null) { | ||
npk.visit(processor, tokens[1]); | ||
} | ||
} else { | ||
log.info("Parameter that is not a nested key: {}", param); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
41 changes: 41 additions & 0 deletions
41
...nt-multilang/src/main/java/software/amazon/kinesis/multilang/NestedPropertyProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright 2023 Amazon.com, Inc. or its affiliates. | ||
* Licensed under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package software.amazon.kinesis.multilang; | ||
|
||
/** | ||
* Defines methods to process {@link NestedPropertyKey}s. | ||
*/ | ||
public interface NestedPropertyProcessor { | ||
|
||
/** | ||
* Set the external id, an optional field to designate who can assume an IAM role. | ||
* | ||
* @param externalId external id used in the service call used to retrieve session credentials | ||
*/ | ||
void acceptExternalId(String externalId); | ||
|
||
/** | ||
* Set the service endpoint where requests are sent. | ||
* | ||
* @param serviceEndpoint the service endpoint either with or without the protocol | ||
* (e.g. https://sns.us-west-1.amazonaws.com or sns.us-west-1.amazonaws.com) | ||
* @param signingRegion the region to use for SigV4 signing of requests (e.g. us-west-1) | ||
* | ||
* @see <a href="https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/client/builder/AwsClientBuilder.EndpointConfiguration.html"> | ||
* AwsClientBuilder.EndpointConfiguration</a> | ||
*/ | ||
void acceptEndpoint(String serviceEndpoint, String signingRegion); | ||
|
||
} |
84 changes: 84 additions & 0 deletions
84
...va/software/amazon/kinesis/multilang/auth/KclSTSAssumeRoleSessionCredentialsProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright 2023 Amazon.com, Inc. or its affiliates. | ||
* Licensed under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package software.amazon.kinesis.multilang.auth; | ||
|
||
import java.util.Arrays; | ||
|
||
import com.amazonaws.auth.AWSSessionCredentials; | ||
import com.amazonaws.auth.AWSSessionCredentialsProvider; | ||
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; | ||
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider.Builder; | ||
import com.amazonaws.client.builder.AwsClientBuilder; | ||
import com.amazonaws.regions.Regions; | ||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; | ||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient; | ||
|
||
import software.amazon.kinesis.multilang.NestedPropertyKey; | ||
import software.amazon.kinesis.multilang.NestedPropertyProcessor; | ||
|
||
/** | ||
* An {@link AWSSessionCredentialsProvider} that is backed by STSAssumeRole. | ||
*/ | ||
public class KclSTSAssumeRoleSessionCredentialsProvider | ||
implements AWSSessionCredentialsProvider, NestedPropertyProcessor { | ||
|
||
private final Builder builder; | ||
|
||
private final STSAssumeRoleSessionCredentialsProvider provider; | ||
|
||
/** | ||
* | ||
* @param params vararg parameters which must include roleArn at index=0, | ||
* and roleSessionName at index=1 | ||
*/ | ||
public KclSTSAssumeRoleSessionCredentialsProvider(final String[] params) { | ||
this(params[0], params[1], Arrays.copyOfRange(params, 2, params.length)); | ||
} | ||
|
||
public KclSTSAssumeRoleSessionCredentialsProvider(final String roleArn, final String roleSessionName, | ||
final String... params) { | ||
builder = new Builder(roleArn, roleSessionName); | ||
NestedPropertyKey.parse(this, params); | ||
provider = builder.build(); | ||
} | ||
|
||
@Override | ||
public AWSSessionCredentials getCredentials() { | ||
return provider.getCredentials(); | ||
} | ||
|
||
@Override | ||
public void refresh() { | ||
// do nothing | ||
} | ||
|
||
@Override | ||
public void acceptExternalId(final String externalId) { | ||
builder.withExternalId(externalId); | ||
} | ||
|
||
@Override | ||
public void acceptEndpoint(final String serviceEndpoint, final String signingRegion) { | ||
final AwsClientBuilder.EndpointConfiguration | ||
endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(serviceEndpoint, signingRegion); | ||
final AWSSecurityTokenService stsClient = | ||
AWSSecurityTokenServiceClient.builder() | ||
.withEndpointConfiguration(endpointConfiguration) | ||
.withRegion(Regions.fromName(signingRegion)) | ||
.build(); | ||
builder.withStsClient(stsClient); | ||
} | ||
|
||
} |
Oops, something went wrong.