public object Execute(ExecutorContext context) { var cmdletContext = context as CmdletContext; var request = new GetPasswordDataRequest(); if (cmdletContext.InstanceId != null) { request.InstanceId = cmdletContext.InstanceId; } var client = Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint); CmdletOutput output; try { var response = CallAWSServiceOperation(client, request); if (string.IsNullOrEmpty(response.PasswordData)) { var msg = string.Format( "Password data is not yet available for instance {0}.\n\nPassword generation and encryption can sometimes take more than 30 minutes. Please wait at least 5 minutes after launching an instance before trying to retrieve the generated password.", cmdletContext.InstanceId); this.WriteWarning(msg); return(new CmdletOutput { ServiceResponse = response }); } if (!cmdletContext.Decrypt) { output = new CmdletOutput { PipelineOutput = response.PasswordData, ServiceResponse = response }; } else { output = new CmdletOutput { PipelineOutput = string.IsNullOrEmpty(cmdletContext.PemFile) ? DecryptViaPemDiscovery(cmdletContext.InstanceId, response, ProfileName, ProfileLocation) : DecryptViaPemFile(cmdletContext.PemFile, response) }; } } catch (Exception e) { output = new CmdletOutput { ErrorResponse = e }; } return(output); }
public Tuple<string, string> WaitForPassword(string instanceId, string key) { var passwordRequest = new GetPasswordDataRequest { InstanceId = instanceId }; var response = _client.GetPasswordData(passwordRequest); if (string.IsNullOrWhiteSpace(response.PasswordData)) { Logger.Info(string.Format("Password not yet ready for {0}, waiting 30 seconds...", instanceId)); Thread.Sleep(30000); return WaitForPassword(instanceId, key); } return new Tuple<string, string>(instanceId, response.GetDecryptedPassword(key)); }
/// <summary> /// Gets a particular instance's password (or at least, the original /// password assigned to the EC2 instance upon creation). /// </summary> /// <param name="amazonEC2"> /// An instance of <see cref="IAmazonEC2" />. /// </param> /// <param name="passwordEncryptionKey"> /// The AWS password encryption key, used in decryption. /// </param> /// <param name="instanceId"> /// The id of the <see cref="Instance" /> to pull back a password for. /// </param> /// <returns> /// The instance's password, as a <see cref="string" /> . /// </returns> private string GetInstancePassword( IAmazonEC2 amazonEC2, string passwordEncryptionKey, string instanceId) { string toReturn = null; this.loggingProvider.Debug( $"Requesitng encrypted password data from " + $"{nameof(Instance)} ID \"{instanceId}\"..."); GetPasswordDataRequest getPasswordDataRequest = new GetPasswordDataRequest(instanceId); GetPasswordDataResponse getPasswordDataResponse = amazonEC2.GetPasswordData(getPasswordDataRequest); this.loggingProvider.Info( $"Password data returned for {nameof(Instance)} ID " + $"\"{instanceId}\"."); try { this.loggingProvider.Debug( $"Using password encryption key to decrypt password " + $"for {nameof(Instance)} ID \"{instanceId}\"..."); toReturn = getPasswordDataResponse .GetDecryptedPassword(passwordEncryptionKey); this.loggingProvider.Info( $"Password for {nameof(Instance)} ID \"{instanceId}\" " + $"decrypted with success."); } catch (CryptographicException) { // We still want to carry on if we can't decrypt the password, // but... this.loggingProvider.Error( $"Could not decrypt password for {nameof(Instance)} " + $"ID \"{instanceId}\"! Are you sure that the password " + $"encryption key is correct? Returning null."); } return(toReturn); }
/// <summary> /// Gets a particular instance's password (or at least, the original /// password assigned to the EC2 instance upon creation). /// </summary> /// <param name="amazonEC2"> /// An instance of <see cref="IAmazonEC2" />. /// </param> /// <param name="passwordEncryptionKeys"> /// Multiple EC2 password encryption keys. /// </param> /// <param name="instanceId"> /// The id of the <see cref="Instance" /> to pull back a password for. /// </param> /// <returns> /// The instance's password, as a <see cref="string" /> . /// </returns> private string GetInstancePassword( IAmazonEC2 amazonEC2, string[] passwordEncryptionKeys, string instanceId) { string toReturn = null; this.loggingProvider.Debug( $"Requesitng encrypted password data from " + $"{nameof(Instance)} ID \"{instanceId}\"..."); GetPasswordDataRequest getPasswordDataRequest = new GetPasswordDataRequest(instanceId); GetPasswordDataResponse getPasswordDataResponse = amazonEC2.GetPasswordData(getPasswordDataRequest); this.loggingProvider.Info( $"Password data returned for {nameof(Instance)} ID " + $"\"{instanceId}\". Attempting to decrypt password with " + $"all {passwordEncryptionKeys.Length} password encryption " + $"key(s) in memory..."); // Only keep going for as long as we don't have a key decrypted. string passwordEncryptionKey = null; for (int i = 0; i < passwordEncryptionKeys.Length && string.IsNullOrEmpty(toReturn); i++) { try { passwordEncryptionKey = passwordEncryptionKeys[i]; this.loggingProvider.Debug( $"Using password encryption key " + $"{i + 1}/{passwordEncryptionKeys.Length} to " + $"decrypt password for {nameof(Instance)} ID " + $"\"{instanceId}\"..."); toReturn = getPasswordDataResponse .GetDecryptedPassword(passwordEncryptionKey); this.loggingProvider.Info( $"Password for {nameof(Instance)} ID " + $"\"{instanceId}\" decrypted with success."); } catch (CryptographicException) { // We still want to carry on if we can't decrypt the // password, but... this.loggingProvider.Warn( $"Could not decrypt password for {nameof(Instance)} " + $"ID \"{instanceId}\" using password encryption key " + $"{i + 1}/{passwordEncryptionKeys.Length}."); } } if (string.IsNullOrEmpty(toReturn)) { this.loggingProvider.Error( $"Could not decrypt password for {nameof(Instance)}: " + $"{passwordEncryptionKeys.Length} password encryption " + $"keys were tried, and none succeeded. Are you sure " + $"that the key file(s) are correct?"); } return(toReturn); }