/*
* Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.auth.profile;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import com.amazonaws.AmazonClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSSessionCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.profile.internal.Profile;
import com.amazonaws.util.ImmutableMapParameter;
public class ProfilesConfigFileWriterTest {
private static final AWSCredentials basicCredA = new BasicAWSCredentials("a", "a");
private static final AWSCredentials basicCredB = new BasicAWSCredentials("b", "b");
private static final AWSCredentials sessionCredC = new BasicSessionCredentials("c", "c", "c");
private static final AWSCredentials sessionCredD = new BasicSessionCredentials("d", "d", "d");
@Test
public void testDumpToFile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
checkCredentialsFile(tmpFile, abcd);
// Rewrite the file with overwrite=true
Profile[] a = { new Profile("a", basicCredA) };
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, a);
checkCredentialsFile(tmpFile, a);
// Rewrite the file with overwrite=false is not allowed
try {
ProfilesConfigFileWriter.dumpToFile(tmpFile, false,
new Profile("a", basicCredA));
fail("Should have thrown exception since the destination file already exists.");
} catch (AmazonClientException expected) {}
}
@Test
public void testModifyProfile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
// a <==> c, b <==> d
Profile[] modified = {
new Profile("a", sessionCredC),
new Profile("b", sessionCredD),
new Profile("c", basicCredA),
new Profile("d", basicCredB)
};
ProfilesConfigFileWriter.modifyOrInsertProfiles(tmpFile, modified);
checkCredentialsFile(tmpFile, modified);
}
@Test
public void testInsertProfile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
// Insert [e] profile
Profile e = new Profile("e", basicCredA);
ProfilesConfigFileWriter.modifyOrInsertProfiles(tmpFile, e);
checkCredentialsFile(tmpFile, abcd[0], abcd[1], abcd[2], abcd[3], e);
}
@Test
public void testModifyAndInsertProfile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
// a <==> c, b <==> d, +e
Profile[] modified = {
new Profile("a", sessionCredC),
new Profile("b", sessionCredD),
new Profile("c", basicCredA),
new Profile("d", basicCredB),
new Profile("e", basicCredA)
};
ProfilesConfigFileWriter.modifyOrInsertProfiles(tmpFile, modified);
checkCredentialsFile(tmpFile, modified);
}
/**
* Tests that comments and unsupported properties are preserved after
* profile modification.
* @throws URISyntaxException
*/
@Test
public void testModifyAndInsertProfile_WithComments() throws IOException, URISyntaxException {
File credWithComments = ProfileResourceLoader.profilesWithComments().asFile();
File tmpFile = copyToTempFile(credWithComments);
String originalContent = FileUtils.readFileToString(tmpFile);
Profile[] expected = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
// a <==> b, c <==> d, also renaming them to uppercase letters
Profile[] modified = {
new Profile("A", basicCredB),
new Profile("B", basicCredA),
new Profile("C", sessionCredD),
new Profile("D", sessionCredC)
};
ProfilesConfigFileWriter.modifyProfiles(tmpFile, ImmutableMapParameter
.of("a", modified[0],
"b", modified[1],
"c", modified[2],
"d", modified[3]));
checkCredentialsFile(tmpFile, modified);
// Sanity check that the content is altered
String modifiedContent = FileUtils.readFileToString(tmpFile);
assertFalse(originalContent.equals(modifiedContent));
// Restore the properties
ProfilesConfigFileWriter.modifyProfiles(tmpFile, ImmutableMapParameter
.of("A", expected[0],
"B", expected[1],
"C", expected[2],
"D", expected[3]));
checkCredentialsFile(tmpFile, expected);
// Check that the content is now the same as the original
String restoredContent = FileUtils.readFileToString(tmpFile);
assertEquals(originalContent, restoredContent);
}
@Test
public void testRenameProfile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
// Rename a to A
Profile[] modified = {
new Profile("A", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.modifyOneProfile(tmpFile, "a", new Profile("A", basicCredA));
checkCredentialsFile(tmpFile, modified);
}
@Test
public void testDeleteProfile() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
// Delete a and c
Profile[] modified = {
new Profile("b", basicCredB),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.deleteProfiles(tmpFile, "a", "c");
checkCredentialsFile(tmpFile, modified);
}
/**
* Tests that the original credentials file is properly restored if the
* in-place modification fails with error.
*/
@Test
public void testInPlaceModificationErrorHandling() throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
Profile[] abcd = {
new Profile("a", basicCredA),
new Profile("b", basicCredB),
new Profile("c", sessionCredC),
new Profile("d", sessionCredD)
};
ProfilesConfigFileWriter.dumpToFile(tmpFile, true, abcd);
String originalContent = FileUtils.readFileToString(tmpFile);
// Insert [e] profile, which throws RuntimeException when the getProperties method is called.
Profile e = new ProfileWithException("e", basicCredA);
try {
ProfilesConfigFileWriter.modifyOrInsertProfiles(tmpFile, e);
fail("An exception is expected.");
} catch(AmazonClientException expected) {}
// Check that the original file is restored
assertTrue(tmpFile.exists());
String restoredContent = FileUtils.readFileToString(tmpFile);
assertEquals(originalContent, restoredContent);
}
/**
* Loads the given credentials file and checks that it contains the same
* set of profiles as expected.
*/
private static void checkCredentialsFile(File file, Profile... expectedProfiles) {
ProfilesConfigFile parsedFile = new ProfilesConfigFile(file);
Map<String, Profile> loadedProfiles = parsedFile.getAllProfiles();
assertTrue(expectedProfiles.length == loadedProfiles.size());
for (Profile expectedProfile : expectedProfiles) {
Profile loadedProfile = loadedProfiles.get(expectedProfile.getProfileName());
assertEqualProfiles(expectedProfile, loadedProfile);
}
}
private static void assertEqualProfiles(Profile expected, Profile actual) {
assertEquals(expected.getProfileName(), actual.getProfileName());
assertEqualCredentials(expected.getCredentials(), actual.getCredentials());
}
private static void assertEqualCredentials(AWSCredentials expected, AWSCredentials actual) {
assertEquals(expected.getAWSAccessKeyId(),
actual.getAWSAccessKeyId());
assertEquals(expected.getAWSAccessKeyId(),
actual.getAWSAccessKeyId());
if (expected instanceof AWSSessionCredentials) {
assertTrue(actual instanceof AWSSessionCredentials);
AWSSessionCredentials expectedSession = (AWSSessionCredentials)expected;
AWSSessionCredentials actualSession = (AWSSessionCredentials)actual;
assertEquals(expectedSession.getSessionToken(),
actualSession.getSessionToken());
} else {
assertFalse(actual instanceof AWSSessionCredentials);
}
}
private static File copyToTempFile(File file) throws IOException {
File tmpFile = File.createTempFile("credentials.", null);
tmpFile.delete();
FileUtils.copyFile(file, tmpFile);
return tmpFile;
}
private static class ProfileWithException extends Profile {
public ProfileWithException(String profileName,
AWSCredentials awsCredentials) {
super(profileName, awsCredentials);
}
@Override
public Map<String, String> getProperties() {
throw new RuntimeException("Some exception...");
}
}
}