-
Notifications
You must be signed in to change notification settings - Fork 323
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow secrets in
AWS_Credential
(#8774)
- Closes #8722
- Loading branch information
Showing
13 changed files
with
194 additions
and
54 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
21 changes: 0 additions & 21 deletions
21
distribution/lib/Standard/AWS/0.0.0-dev/src/Internal/Auth.enso
This file was deleted.
Oops, something went wrong.
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
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
11 changes: 11 additions & 0 deletions
11
std-bits/aws/src/main/java/org/enso/aws/AwsCredential.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,11 @@ | ||
package org.enso.aws; | ||
|
||
import org.enso.base.enso_cloud.HideableValue; | ||
|
||
public sealed interface AwsCredential { | ||
record Key(HideableValue accessKeyId, HideableValue secretAccessKey) implements AwsCredential {} | ||
|
||
record Profile(String name) implements AwsCredential {} | ||
|
||
record Default() implements AwsCredential {} | ||
} |
48 changes: 48 additions & 0 deletions
48
std-bits/aws/src/main/java/org/enso/aws/ClientBuilder.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,48 @@ | ||
package org.enso.aws; | ||
|
||
import org.enso.base.enso_cloud.ExternalLibrarySecretHelper; | ||
import org.enso.base.enso_cloud.HideableValue; | ||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; | ||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; | ||
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; | ||
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; | ||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; | ||
import software.amazon.awssdk.services.s3.S3Client; | ||
|
||
public class ClientBuilder { | ||
private final AwsCredential awsCredential; | ||
|
||
public ClientBuilder(AwsCredential credential) { | ||
this.awsCredential = credential; | ||
} | ||
|
||
public S3Client buildS3Client() { | ||
return S3Client.builder().credentialsProvider(unsafeBuildCredentialProvider()).build(); | ||
} | ||
|
||
/** | ||
* The {@code AwsCredentialsProviders} may leak secrets, so it should never be returned to user | ||
* code. | ||
*/ | ||
private AwsCredentialsProvider unsafeBuildCredentialProvider() { | ||
return switch (this.awsCredential) { | ||
case AwsCredential.Default unused -> DefaultCredentialsProvider.create(); | ||
case AwsCredential.Key key -> { | ||
AwsBasicCredentials credentials = | ||
AwsBasicCredentials.create( | ||
unsafeResolveSecrets(key.accessKeyId()), | ||
unsafeResolveSecrets(key.secretAccessKey())); | ||
yield StaticCredentialsProvider.create(credentials); | ||
} | ||
case AwsCredential.Profile profile -> ProfileCredentialsProvider.create(profile.name()); | ||
}; | ||
} | ||
|
||
/** | ||
* This function is allowed access to secrets. Extra care should be taken to ensure its result is | ||
* not leaked. | ||
*/ | ||
private String unsafeResolveSecrets(HideableValue value) { | ||
return ExternalLibrarySecretHelper.resolveValue(value); | ||
} | ||
} |
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
54 changes: 54 additions & 0 deletions
54
std-bits/base/src/main/java/org/enso/base/enso_cloud/ExternalLibrarySecretHelper.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,54 @@ | ||
package org.enso.base.enso_cloud; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
/** | ||
* An entry point allowing external libraries to access Enso secrets. | ||
* | ||
* <p>It will only allow access from trusted code locations. | ||
*/ | ||
public final class ExternalLibrarySecretHelper extends SecretValueResolver { | ||
public static String resolveValue(HideableValue hideableValue) throws EnsoSecretAccessDenied { | ||
checkAccess(); | ||
return SecretValueResolver.resolveValue(hideableValue); | ||
} | ||
|
||
/** | ||
* Checks the current stack trace to find the caller and checks if it is one of the allowed | ||
* locations. | ||
* | ||
* <p>This is a very rudimentary approach to the access control, and it is not very extensible, as | ||
* it requires updating std-base whenever a new library that needs access to secrets is added. | ||
* However, it seems like the best simple solution for now. | ||
* | ||
* <p>Later we may want to replace it with some other solution, e.g. a key that trusted libraries | ||
* will use to 'sign' their class name, proving that they can be trusted, without the need to | ||
* update std-base whenever a new library is added. | ||
*/ | ||
private static void checkAccess() throws EnsoSecretAccessDenied { | ||
var accessLocation = | ||
StackWalker.getInstance() | ||
.walk( | ||
(stackFrameStream -> { | ||
Optional<StackWalker.StackFrame> firstClientFrame = | ||
stackFrameStream.skip(2).findFirst(); | ||
if (firstClientFrame.isEmpty()) { | ||
throw new IllegalStateException("Unable to find client frame."); | ||
} | ||
|
||
var frame = firstClientFrame.get(); | ||
return new AccessLocation(frame.getClassName(), frame.getMethodName()); | ||
})); | ||
|
||
boolean isAllowed = allowedAccessLocations.contains(accessLocation); | ||
if (!isAllowed) { | ||
throw new EnsoSecretAccessDenied(); | ||
} | ||
} | ||
|
||
private record AccessLocation(String className, String method) {} | ||
|
||
private static final List<AccessLocation> allowedAccessLocations = | ||
List.of(new AccessLocation("org.enso.aws.ClientBuilder", "unsafeResolveSecrets")); | ||
} |
25 changes: 25 additions & 0 deletions
25
std-bits/base/src/main/java/org/enso/base/enso_cloud/SecretValueResolver.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,25 @@ | ||
package org.enso.base.enso_cloud; | ||
|
||
sealed class SecretValueResolver permits EnsoSecretHelper, ExternalLibrarySecretHelper { | ||
/** | ||
* Gets the value of an HideableValue resolving secrets. | ||
* | ||
* @param value The value to resolve. | ||
* @return The pair's value. Should not be returned to Enso. | ||
*/ | ||
protected static String resolveValue(HideableValue value) { | ||
return switch (value) { | ||
case HideableValue.PlainValue plainValue -> plainValue.value(); | ||
case HideableValue.SecretValue secretValue -> { | ||
yield EnsoSecretReader.readSecret(secretValue.secretId()); | ||
} | ||
case HideableValue.ConcatValues concatValues -> { | ||
String left = resolveValue(concatValues.left()); | ||
String right = resolveValue(concatValues.right()); | ||
yield left + right; | ||
} | ||
case HideableValue.Base64EncodeValue base64EncodeValue -> HideableValue.Base64EncodeValue | ||
.encode(resolveValue(base64EncodeValue.value())); | ||
}; | ||
} | ||
} |
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