use of ch.cyberduck.core.AsciiRandomStringService in project cyberduck by iterate-ch.
the class SwiftAccountLoader method operate.
@Override
protected Map<Region, AccountInfo> operate(final PasswordCallback callback, final Path file) throws BackgroundException {
final Map<Region, AccountInfo> accounts = new ConcurrentHashMap<>();
for (Region region : session.getClient().getRegions()) {
try {
final AccountInfo info = session.getClient().getAccountInfo(region);
if (log.isInfoEnabled()) {
log.info(String.format("Signing key is %s", info.getTempUrlKey()));
}
if (StringUtils.isBlank(info.getTempUrlKey())) {
// Update account info setting temporary URL key
try {
final String key = new AsciiRandomStringService().random();
if (log.isDebugEnabled()) {
log.debug(String.format("Set acccount temp URL key to %s", key));
}
session.getClient().updateAccountMetadata(region, Collections.singletonMap("X-Account-Meta-Temp-URL-Key", key));
info.setTempUrlKey(key);
} catch (GenericException e) {
log.warn(String.format("Ignore failure %s updating account metadata", e));
}
}
accounts.put(region, info);
} catch (GenericException e) {
if (e.getHttpStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) {
log.warn(String.format("Ignore failure %s for region %s", e, region));
continue;
}
throw new SwiftExceptionMappingService().map(e);
} catch (IOException e) {
throw new DefaultIOExceptionMappingService().map(e);
}
}
return accounts;
}
use of ch.cyberduck.core.AsciiRandomStringService in project cyberduck by iterate-ch.
the class STSCredentialsConfigurator method configure.
public Credentials configure(final Host host) throws LoginFailureException, LoginCanceledException {
final Credentials credentials = new Credentials(host.getCredentials());
// See https://docs.aws.amazon.com/sdkref/latest/guide/creds-config-files.html for configuration behavior
final Local awsDirectory = LocalFactory.get(LocalFactory.get(), ".aws");
final Local configFile = LocalFactory.get(awsDirectory, "config");
final Local credentialsFile = LocalFactory.get(awsDirectory, "credentials");
// Profile can be null. The default profile from the configuration will be loaded
final String profile = host.getCredentials().getUsername();
if (log.isDebugEnabled()) {
log.debug(String.format("Look for profile name %s in %s and %s", profile, configFile, credentialsFile));
}
// Iterating all profiles on our own because AWSProfileCredentialsConfigurator does not support MFA tokens
final Map<String, Map<String, String>> allProfileProperties = new HashMap<>();
try {
final Map<String, Map<String, String>> credentialsFileProfileProperties = new ProfilesConfigFileLoaderHelper().parseProfileProperties(credentialsFile);
allProfileProperties.putAll(credentialsFileProfileProperties);
final Map<String, Map<String, String>> configFileProfileProperties = new ProfilesConfigFileLoaderHelper().parseProfileProperties(configFile);
for (Map.Entry<String, Map<String, String>> entry : configFileProfileProperties.entrySet()) {
final String profileName = entry.getKey();
final Map<String, String> configFileProperties = entry.getValue();
final Map<String, String> credentialsFileProperties = allProfileProperties.get(profileName);
// If the credentials file had properties, then merge them in
if (credentialsFileProperties != null) {
configFileProperties.putAll(credentialsFileProperties);
}
allProfileProperties.put(profileName, configFileProperties);
}
} catch (AccessDeniedException | IllegalArgumentException | IOException e) {
log.warn(String.format("Failure reading %s and %s", configFile, credentialsFile), e);
return credentials;
}
if (allProfileProperties.isEmpty()) {
log.warn("Missing configuration file ~/.aws/credentials or ~/.aws/config. Skip auto configuration");
return host.getCredentials();
}
// Convert the loaded property map to credential objects
final Map<String, BasicProfile> profilesByName = new LinkedHashMap<>();
for (Map.Entry<String, Map<String, String>> entry : allProfileProperties.entrySet()) {
String profileName = entry.getKey();
Map<String, String> properties = entry.getValue();
profilesByName.put(profileName, new BasicProfile(profileName, properties));
}
final Map<String, BasicProfile> profiles = new AllProfiles(profilesByName).getProfiles();
final Optional<Map.Entry<String, BasicProfile>> optional = profiles.entrySet().stream().filter(new Predicate<Map.Entry<String, BasicProfile>>() {
@Override
public boolean test(final Map.Entry<String, BasicProfile> entry) {
final String profileName = entry.getKey();
final BasicProfile basicProfile = entry.getValue();
final String awsAccessIdKey = basicProfile.getAwsAccessIdKey();
// Matching access key or profile name
if (StringUtils.equals(profileName, profile) || StringUtils.equals(awsAccessIdKey, profile)) {
if (log.isDebugEnabled()) {
log.debug(String.format("Found matching profile %s", profile));
}
return true;
}
return false;
}
}).findFirst();
if (optional.isPresent()) {
final Map.Entry<String, BasicProfile> entry = optional.get();
final BasicProfile basicProfile = entry.getValue();
if (basicProfile.isRoleBasedProfile()) {
if (log.isDebugEnabled()) {
log.debug(String.format("Configure credentials from role based profile %s", basicProfile.getProfileName()));
}
if (StringUtils.isBlank(basicProfile.getRoleSourceProfile())) {
throw new LoginFailureException(String.format("Missing source profile reference in profile %s", basicProfile.getProfileName()));
} else if (!profiles.containsKey(basicProfile.getRoleSourceProfile())) {
throw new LoginFailureException(String.format("Missing source profile with name %s", basicProfile.getRoleSourceProfile()));
} else {
final BasicProfile sourceProfile = profiles.get(basicProfile.getRoleSourceProfile());
// If a profile defines the role_arn property then the profile is treated as an assume role profile
final AWSSecurityTokenService service = this.getTokenService(host, host.getRegion(), sourceProfile.getAwsAccessIdKey(), sourceProfile.getAwsSecretAccessKey(), sourceProfile.getAwsSessionToken());
final String tokenCode;
if (basicProfile.getProperties().containsKey("mfa_serial")) {
tokenCode = prompt.prompt(host, LocaleFactory.localizedString("Provide additional login credentials", "Credentials"), String.format("%s %s", LocaleFactory.localizedString("Multi-Factor Authentication", "S3"), basicProfile.getPropertyValue("mfa_serial")), new LoginOptions(host.getProtocol()).password(true).passwordPlaceholder(LocaleFactory.localizedString("MFA Authentication Code", "S3")).keychain(false)).getPassword();
} else {
tokenCode = null;
}
final Integer durationSeconds;
if (basicProfile.getProperties().containsKey("duration_seconds")) {
durationSeconds = Integer.valueOf(basicProfile.getPropertyValue("duration_seconds"));
} else {
durationSeconds = null;
}
// Starts a new session by sending a request to the AWS Security Token Service (STS) to assume a
// Role using the long lived AWS credentials
final AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest().withExternalId(basicProfile.getRoleExternalId()).withRoleArn(basicProfile.getRoleArn()).withSerialNumber(basicProfile.getPropertyValue("mfa_serial")).withTokenCode(tokenCode).withRoleSessionName(new AsciiRandomStringService().random()).withDurationSeconds(durationSeconds);
if (log.isDebugEnabled()) {
log.debug(String.format("Request %s from %s", assumeRoleRequest, service));
}
try {
final AssumeRoleResult assumeRoleResult = service.assumeRole(assumeRoleRequest);
if (log.isDebugEnabled()) {
log.debug(String.format("Set credentials from %s", assumeRoleResult));
}
credentials.setUsername(assumeRoleResult.getCredentials().getAccessKeyId());
credentials.setPassword(assumeRoleResult.getCredentials().getSecretAccessKey());
credentials.setToken(assumeRoleResult.getCredentials().getSessionToken());
} catch (AWSSecurityTokenServiceException e) {
throw new LoginFailureException(e.getErrorMessage(), e);
}
}
} else {
if (log.isDebugEnabled()) {
log.debug(String.format("Configure credentials from basic profile %s", basicProfile.getProfileName()));
}
final Map<String, String> profileProperties = basicProfile.getProperties();
if (profileProperties.containsKey("sso_start_url")) {
// Read cached SSO credentials
final CachedCredential cached = this.fetchSsoCredentials(credentials, profileProperties, awsDirectory);
credentials.setUsername(cached.accessKey);
credentials.setPassword(cached.secretKey);
credentials.setToken(cached.sessionToken);
} else if (StringUtils.isNotBlank(basicProfile.getAwsSessionToken())) {
// No need to obtain session token if preconfigured in profile
if (log.isDebugEnabled()) {
log.debug(String.format("Set session token credentials from profile %s", profile));
}
credentials.setUsername(basicProfile.getAwsAccessIdKey());
credentials.setPassword(basicProfile.getAwsSecretAccessKey());
credentials.setToken(basicProfile.getAwsSessionToken());
} else {
if (host.getProtocol().isTokenConfigurable()) {
// Obtain session token
if (log.isDebugEnabled()) {
log.debug(String.format("Get session token from credentials in profile %s", basicProfile.getProfileName()));
}
final AWSSecurityTokenService service = this.getTokenService(host, host.getRegion(), basicProfile.getAwsAccessIdKey(), basicProfile.getAwsSecretAccessKey(), basicProfile.getAwsSessionToken());
final GetSessionTokenRequest sessionTokenRequest = new GetSessionTokenRequest();
if (log.isDebugEnabled()) {
log.debug(String.format("Request %s from %s", sessionTokenRequest, service));
}
try {
final GetSessionTokenResult sessionTokenResult = service.getSessionToken(sessionTokenRequest);
if (log.isDebugEnabled()) {
log.debug(String.format("Set credentials from %s", sessionTokenResult));
}
credentials.setUsername(sessionTokenResult.getCredentials().getAccessKeyId());
credentials.setPassword(sessionTokenResult.getCredentials().getSecretAccessKey());
credentials.setToken(sessionTokenResult.getCredentials().getSessionToken());
} catch (AWSSecurityTokenServiceException e) {
throw new LoginFailureException(e.getErrorMessage(), e);
}
} else {
if (log.isDebugEnabled()) {
log.debug(String.format("Set static credentials from profile %s", basicProfile.getProfileName()));
}
credentials.setUsername(basicProfile.getAwsAccessIdKey());
credentials.setPassword(basicProfile.getAwsSecretAccessKey());
}
}
}
}
return credentials;
}
use of ch.cyberduck.core.AsciiRandomStringService in project cyberduck by iterate-ch.
the class S3VersionedObjectListServiceTest method testEnableVersioningExistingFiles.
@Test
public void testEnableVersioningExistingFiles() throws Exception {
final Path bucket = new S3DirectoryFeature(session, new S3WriteFeature(session)).mkdir(new Path(new AsciiRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume)), new TransferStatus());
assertTrue(new S3FindFeature(session).find(bucket));
final Path file = new S3TouchFeature(session).touch(new Path(bucket, new AsciiRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus());
final S3WriteFeature feature = new S3WriteFeature(session);
{
final byte[] content = RandomUtils.nextBytes(1024);
final TransferStatus status = new TransferStatus();
status.setLength(content.length);
status.setChecksum(new SHA256ChecksumCompute().compute(new ByteArrayInputStream(content), status));
final HttpResponseOutputStream<StorageObject> out = feature.write(file, status, new DisabledConnectionCallback());
new StreamCopier(status, status).transfer(new ByteArrayInputStream(content), out);
out.close();
assertEquals(content.length, new DefaultAttributesFinderFeature(session).find(file).getSize());
final PathAttributes attr = new DefaultAttributesFinderFeature(session).find(file);
assertEquals(content.length, attr.getSize());
assertNull(new DefaultAttributesFinderFeature(session).find(file).getVersionId());
}
session.getFeature(Versioning.class).setConfiguration(bucket, new DisabledPasswordCallback(), new VersioningConfiguration(true));
assertNull(new DefaultAttributesFinderFeature(session).find(file).getVersionId());
{
final byte[] content = RandomUtils.nextBytes(1024);
final TransferStatus status = new TransferStatus();
status.setLength(content.length);
status.setChecksum(new SHA256ChecksumCompute().compute(new ByteArrayInputStream(content), status));
final HttpResponseOutputStream<StorageObject> out = feature.write(file, status, new DisabledConnectionCallback());
new StreamCopier(status, status).transfer(new ByteArrayInputStream(content), out);
out.close();
assertEquals(content.length, new DefaultAttributesFinderFeature(session).find(file).getSize());
final PathAttributes attr = new DefaultAttributesFinderFeature(session).find(file);
assertEquals(content.length, attr.getSize());
assertNotNull(attr.getVersionId());
}
final AttributedList<Path> list = new S3VersionedObjectListService(session, 1, true).list(bucket, new DisabledListProgressListener()).filter(new Filter<Path>() {
@Override
public boolean accept(final Path f) {
return new SimplePathPredicate(file).test(f);
}
@Override
public Pattern toPattern() {
return null;
}
});
assertEquals(2, list.size());
assertEquals(1, list.get(0).attributes().getVersions().size());
assertEquals(0, list.get(1).attributes().getVersions().size());
assertSame(list.get(0).attributes().getVersions().get(0), list.get(1));
new S3DefaultDeleteFeature(session).delete(Arrays.asList(new Path(file).withAttributes(new PathAttributes().withVersionId("null")), new Path(file).withAttributes(new DefaultAttributesFinderFeature(session).find(file)), bucket), new DisabledLoginCallback(), new Delete.DisabledCallback());
}
use of ch.cyberduck.core.AsciiRandomStringService in project cyberduck by iterate-ch.
the class S3MoveFeatureTest method testMoveWithServerSideEncryptionBucketPolicy.
@Test
public void testMoveWithServerSideEncryptionBucketPolicy() throws Exception {
final Path container = new Path("sse-test-us-east-1-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume));
final Path test = new Path(container, new AsciiRandomStringService().random(), EnumSet.of(Path.Type.file));
final S3TouchFeature touch = new S3TouchFeature(session);
final TransferStatus status = new TransferStatus();
status.setEncryption(S3EncryptionFeature.SSE_AES256);
touch.touch(test, status);
assertTrue(new S3FindFeature(session).find(test));
final Path renamed = new Path(container, new AsciiRandomStringService().random(), EnumSet.of(Path.Type.file));
new S3MoveFeature(session).move(test, renamed, new TransferStatus(), new Delete.DisabledCallback(), new DisabledConnectionCallback());
assertFalse(new S3FindFeature(session).find(test));
assertTrue(new S3FindFeature(session).find(renamed));
new S3DefaultDeleteFeature(session).delete(Collections.singletonList(renamed), new DisabledLoginCallback(), new Delete.DisabledCallback());
}
use of ch.cyberduck.core.AsciiRandomStringService in project cyberduck by iterate-ch.
the class S3MoveFeatureTest method testMoveVersioned.
@Test
public void testMoveVersioned() throws Exception {
final Path container = new Path("versioning-test-us-east-1-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume));
Path test = new Path(container, new AsciiRandomStringService().random(), EnumSet.of(Path.Type.file));
assertNotNull(new S3TouchFeature(session).touch(test, new TransferStatus().withMime("text/plain")).attributes().getVersionId());
assertTrue(new S3FindFeature(session).find(test));
// Write some data to add a new version
final S3WriteFeature feature = new S3WriteFeature(session);
final byte[] content = RandomUtils.nextBytes(10);
final TransferStatus status = new TransferStatus().withMime("text/plain");
status.setLength(content.length);
status.setChecksum(new SHA256ChecksumCompute().compute(new ByteArrayInputStream(content), status));
final HttpResponseOutputStream<StorageObject> out = feature.write(test, status, new DisabledConnectionCallback());
new StreamCopier(status, status).transfer(new ByteArrayInputStream(content), out);
out.close();
// Get new path with updated version id
final AttributedList<Path> list = new S3ListService(session).list(container, new DisabledListProgressListener());
for (Path path : list) {
if (new SimplePathPredicate(test).test(path)) {
test = path;
break;
}
}
final Path renamed = new Path(container, String.format("%s-renamed", test.getName()), EnumSet.of(Path.Type.file));
new S3MoveFeature(session).move(test, renamed, new TransferStatus(), new Delete.DisabledCallback(), new DisabledConnectionCallback());
assertTrue(new S3FindFeature(session).find(test));
assertTrue(new S3FindFeature(session).find(renamed));
// Ensure that the latest version of the source file is a delete marker
for (Path path : new S3ListService(session).list(container, new DisabledListProgressListener())) {
if (new SimplePathPredicate(test).test(path)) {
assertTrue(path.attributes().isDuplicate());
assertTrue(new S3AttributesFinderFeature(session, true).find(path).isDuplicate());
assertTrue(new S3AttributesFinderFeature(session, false).find(path).isDuplicate());
break;
}
}
final Map<String, String> metadata = new S3MetadataFeature(session, new S3AccessControlListFeature(session)).getMetadata(renamed);
assertFalse(metadata.isEmpty());
assertEquals("text/plain", metadata.get("Content-Type"));
new S3DefaultDeleteFeature(session).delete(Collections.singletonList(renamed), new DisabledLoginCallback(), new Delete.DisabledCallback());
}
Aggregations