io.trino.filesystem.s3.S3SecurityMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of trino-filesystem-s3 Show documentation
Show all versions of trino-filesystem-s3 Show documentation
Trino - S3 file system support
/*
* 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 io.trino.filesystem.s3;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.trino.filesystem.Location;
import io.trino.spi.security.ConnectorIdentity;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
public final class S3SecurityMapping
{
private final Predicate user;
private final Predicate> group;
private final Predicate prefix;
private final Optional iamRole;
private final Optional roleSessionName;
private final Set allowedIamRoles;
private final Optional kmsKeyId;
private final Set allowedKmsKeyIds;
private final Optional credentials;
private final boolean useClusterDefault;
private final Optional endpoint;
private final Optional region;
@JsonCreator
public S3SecurityMapping(
@JsonProperty("user") Optional user,
@JsonProperty("group") Optional group,
@JsonProperty("prefix") Optional prefix,
@JsonProperty("iamRole") Optional iamRole,
@JsonProperty("roleSessionName") Optional roleSessionName,
@JsonProperty("allowedIamRoles") Optional> allowedIamRoles,
@JsonProperty("kmsKeyId") Optional kmsKeyId,
@JsonProperty("allowedKmsKeyIds") Optional> allowedKmsKeyIds,
@JsonProperty("accessKey") Optional accessKey,
@JsonProperty("secretKey") Optional secretKey,
@JsonProperty("useClusterDefault") Optional useClusterDefault,
@JsonProperty("endpoint") Optional endpoint,
@JsonProperty("region") Optional region)
{
this.user = user
.map(S3SecurityMapping::toPredicate)
.orElse(_ -> true);
this.group = group
.map(S3SecurityMapping::toPredicate)
.map(S3SecurityMapping::anyMatch)
.orElse(_ -> true);
this.prefix = prefix
.map(Location::of)
.map(S3Location::new)
.map(S3SecurityMapping::prefixPredicate)
.orElse(_ -> true);
this.iamRole = requireNonNull(iamRole, "iamRole is null");
this.roleSessionName = requireNonNull(roleSessionName, "roleSessionName is null");
checkArgument(roleSessionName.isEmpty() || iamRole.isPresent(), "iamRole must be provided when roleSessionName is provided");
this.allowedIamRoles = ImmutableSet.copyOf(allowedIamRoles.orElse(ImmutableList.of()));
this.kmsKeyId = requireNonNull(kmsKeyId, "kmsKeyId is null");
this.allowedKmsKeyIds = ImmutableSet.copyOf(allowedKmsKeyIds.orElse(ImmutableList.of()));
requireNonNull(accessKey, "accessKey is null");
requireNonNull(secretKey, "secretKey is null");
checkArgument(accessKey.isPresent() == secretKey.isPresent(), "accessKey and secretKey must be provided together");
this.credentials = accessKey.map(access -> AwsBasicCredentials.create(access, secretKey.get()));
this.useClusterDefault = useClusterDefault.orElse(false);
boolean roleOrCredentialsArePresent = !this.allowedIamRoles.isEmpty() || iamRole.isPresent() || credentials.isPresent();
checkArgument(this.useClusterDefault != roleOrCredentialsArePresent, "must either allow useClusterDefault role or provide role and/or credentials");
checkArgument(!this.useClusterDefault || this.kmsKeyId.isEmpty(), "KMS key ID cannot be provided together with useClusterDefault");
this.endpoint = requireNonNull(endpoint, "endpoint is null");
this.region = requireNonNull(region, "region is null");
}
boolean matches(ConnectorIdentity identity, S3Location location)
{
return user.test(identity.getUser()) &&
group.test(identity.getGroups()) &&
prefix.test(location);
}
public Optional iamRole()
{
return iamRole;
}
public Optional roleSessionName()
{
return roleSessionName;
}
public Set allowedIamRoles()
{
return allowedIamRoles;
}
public Optional kmsKeyId()
{
return kmsKeyId;
}
public Set allowedKmsKeyIds()
{
return allowedKmsKeyIds;
}
public Optional credentials()
{
return credentials;
}
public boolean useClusterDefault()
{
return useClusterDefault;
}
public Optional endpoint()
{
return endpoint;
}
public Optional region()
{
return region;
}
private static Predicate prefixPredicate(S3Location prefix)
{
return value -> prefix.bucket().equals(value.bucket()) &&
value.key().startsWith(prefix.key());
}
private static Predicate toPredicate(Pattern pattern)
{
return value -> pattern.matcher(value).matches();
}
private static Predicate> anyMatch(Predicate predicate)
{
return values -> values.stream().anyMatch(predicate);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy