/* * Copyright 2008-2012 Amazon Technologies, Inc. * * 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://aws.amazon.com/apache2.0 * * 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.eclipse.core.accounts.profiles; import java.io.File; import java.io.IOException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ui.statushandlers.StatusManager; 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.ProfilesConfigFileWriter; import com.amazonaws.auth.profile.internal.Profile; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.accounts.AccountCredentialsConfiguration; import com.amazonaws.eclipse.core.preferences.PreferenceConstants; /** * Concrete implementation of AccountCredentialsConfiguration, which uses the * credential profiles file to persist the credential configurations. */ public class SdkProfilesCredentialsConfiguration extends AccountCredentialsConfiguration { /** * Use this preference store to save the mapping from an accountId to a * profile name. */ private final IPreferenceStore prefStore; /** * The profile instance loaded from the credentials file. */ private Profile profile; /** * The name of the preference property that maps an internal account id to * the name of the credential profile associated with the account. */ private final String profileNamePreferenceName; /** The property values set in memory */ private String profileNameInMemory; private String accessKeyInMemory; private String secretKeyInMemory; private Boolean useSessionToken; private String sessionTokenInMemory; public SdkProfilesCredentialsConfiguration( IPreferenceStore prefStore, String accountId, Profile profile) { if (prefStore == null) throw new IllegalAccessError("prefStore must not be null."); if (accountId == null) throw new IllegalAccessError("accountId must not be null."); if (profile == null) throw new IllegalAccessError("profile must not be null."); this.prefStore = prefStore; this.profile = profile; this.profileNamePreferenceName = String.format("%s:%s", accountId, PreferenceConstants.P_CREDENTIAL_PROFILE_NAME); } /* All credential-related information are B64-encoded */ /** * Use the profile name as the account name shown in the toolkit UI. */ @Override public String getAccountName() { return this.profileNameInMemory != null ? this.profileNameInMemory : profile.getProfileName(); } @Override public void setAccountName(String accountName) { this.profileNameInMemory = accountName; } @Override public String getAccessKey() { return this.accessKeyInMemory != null ? this.accessKeyInMemory : profile.getCredentials().getAWSAccessKeyId(); } @Override public void setAccessKey(String accessKey) { this.accessKeyInMemory = accessKey; } @Override public String getSecretKey() { return this.secretKeyInMemory != null ? this.secretKeyInMemory : profile.getCredentials().getAWSSecretKey(); } @Override public void setSecretKey(String secretKey) { this.secretKeyInMemory = secretKey; } @Override public boolean isUseSessionToken() { if (useSessionToken != null) { return useSessionToken; } return isSessionCredentials(profile.getCredentials()); } @Override public void setUseSessionToken(boolean useSessionToken) { this.useSessionToken = useSessionToken; } @Override public String getSessionToken() { if (sessionTokenInMemory != null) { return sessionTokenInMemory; } return getSessionToken(profile.getCredentials()); } @Override public void setSessionToken(String sessionToken) { this.sessionTokenInMemory = sessionToken; } private String getSessionToken(AWSCredentials creds) { if (creds instanceof AWSSessionCredentials) { return ((AWSSessionCredentials)creds).getSessionToken(); } else { return null; } } private boolean isSessionCredentials(AWSCredentials creds) { return getSessionToken(creds) != null; } /** * Write all the in-memory property values in the credentials file. */ @Override public void save() { if (isDirty()) { // Clean up the properties before saving it if (profileNameInMemory != null) { profileNameInMemory = profileNameInMemory.trim(); } if (accessKeyInMemory != null) { accessKeyInMemory = accessKeyInMemory.trim(); } if (secretKeyInMemory != null) { secretKeyInMemory = secretKeyInMemory.trim(); } if (sessionTokenInMemory != null) { sessionTokenInMemory = sessionTokenInMemory.trim(); } AWSCredentials creds = null; if (isUseSessionToken()) { creds = new BasicSessionCredentials(getAccessKey(), getSecretKey(), getSessionToken()); } else { creds = new BasicAWSCredentials(getAccessKey(), getSecretKey()); } Profile newProfile = new Profile(getAccountName(), creds); // Output the new profile to the credentials file File credentialsFile = new File( prefStore.getString( PreferenceConstants.P_CREDENTIAL_PROFILE_FILE_LOCATION)); // Create the file if it doesn't exist yet // TODO: ideally this should be handled by ProfilesConfigFileWriter if ( !credentialsFile.exists() ) { try { if (credentialsFile.getParentFile() != null) { credentialsFile.getParentFile().mkdirs(); } credentialsFile.createNewFile(); } catch (IOException ioe) { StatusManager.getManager().handle( new Status(IStatus.ERROR, AwsToolkitCore.PLUGIN_ID, "Failed to create credentials file at " + credentialsFile.getAbsolutePath(), ioe), StatusManager.SHOW); } } String prevProfileName = profile.getProfileName(); ProfilesConfigFileWriter.modifyOneProfile(credentialsFile, prevProfileName, newProfile); // Persist the profile metadata in the preference store: // accountId:credentialProfileName=profileName prefStore.setValue( profileNamePreferenceName, newProfile.getProfileName()); this.profile = newProfile; clearInMemoryValue(); } } /** * Deletes the profile name property associated with this account in the * preferece store instance. Also remove the profile from the credentials * file. */ public void delete() { prefStore.setToDefault(profileNamePreferenceName); File credentialsFile = new File( prefStore.getString( PreferenceConstants.P_CREDENTIAL_PROFILE_FILE_LOCATION)); String prevProfileName = profile.getProfileName(); ProfilesConfigFileWriter.deleteProfiles(credentialsFile, prevProfileName); clearInMemoryValue(); } @Override public boolean isDirty() { return (hasPropertyChanged(profile.getProfileName(), profileNameInMemory) || hasPropertyChanged(profile.getCredentials().getAWSAccessKeyId(), accessKeyInMemory) || hasPropertyChanged(profile.getCredentials().getAWSSecretKey(), secretKeyInMemory) || hasPropertyChanged(isSessionCredentials(profile.getCredentials()), useSessionToken) || hasPropertyChanged(getSessionToken(profile.getCredentials()), sessionTokenInMemory)); } /** * @return True if the new value of the property is non null and differs * from the original, false otherwise */ private boolean hasPropertyChanged(Object originalValue, Object newValue) { return newValue != null && !newValue.equals(originalValue); } private void clearInMemoryValue() { profileNameInMemory = null; accessKeyInMemory = null; secretKeyInMemory = null; useSessionToken = null; sessionTokenInMemory = null; } }