private AWSPSCredentials PromptUserForCredentials()
        {
            var storedCredentials = SettingsStore.GetProfileInfo(ProfileLocation);

            if (storedCredentials.Any())
            {
                // If there are stored credentials, ask user which ones to use, or enter new ones
                var choices = new Collection <ChoiceDescription>();
                choices.Add(new ChoiceDescription("<Create new credentials set>"));
                foreach (var profileInfo in storedCredentials)
                {
                    // help message cannot be null
                    var helpMessage = profileInfo.ProfileLocation == null ? profileInfo.StoreTypeName : profileInfo.ProfileLocation;
                    choices.Add(new ChoiceDescription(profileInfo.ProfileName, helpMessage));
                }

                var choice = Host.UI.PromptForChoice("Saved credentials found", CredentialsPrompt, choices, 0);
                if (choice != 0)
                {
                    var            chosenCredentials = choices[choice];
                    AWSCredentials awsCredentials;
                    if (SettingsStore.TryGetAWSCredentials(chosenCredentials.Label, ProfileLocation, out awsCredentials))
                    {
                        return(new AWSPSCredentials(awsCredentials, chosenCredentials.Label, CredentialsSource.Profile));
                    }
                }
            }

            var descriptions = new Collection <FieldDescription>();

            descriptions.Add(new FieldDescription(AccessKeyFieldName));
            descriptions.Add(new FieldDescription(SecretKeyFieldName));
            var response = Host.UI.Prompt("Credentials", "Please enter your AWS Access and Secret Keys", descriptions);

            var accessKey = response[AccessKeyFieldName].BaseObject as string;
            var secretKey = response[SecretKeyFieldName].BaseObject as string;

            if (string.IsNullOrEmpty(accessKey))
            {
                throw new ArgumentOutOfRangeException(AccessKeyFieldName + " is not set");
            }
            if (string.IsNullOrEmpty(secretKey))
            {
                throw new ArgumentOutOfRangeException(SecretKeyFieldName + " is not set");
            }

            var credentials = new BasicAWSCredentials(accessKey, secretKey);

            // this set will be saved as our default name
            return(new AWSPSCredentials(credentials, SettingsStore.PSDefaultSettingName, CredentialsSource.Profile));
        }
Example #2
0
        private static bool TryLoad(
            string name,
            string profileLocation,
            ref RegionEndpoint region,
            ref RegionSource source)
        {
            if (SettingsStore.TryGetProfile(name, profileLocation, out var profile) && profile.Region != null)
            {
                region = profile.Region;
                source = RegionSource.Saved;
                return(true);
            }

            return(false);
        }
        private void GetFromDefaultProfile(out AWSPSCredentials awsPSCredentialsFromDefaultProfile, out RegionEndpoint regionFromDefaultProfile)
        {
            CredentialProfile profile;

            if (SettingsStore.TryGetProfile(SettingsStore.PSDefaultSettingName, ProfileLocation, out profile))
            {
                AWSCredentials defaultAWSCredentials;
                if (SettingsStore.TryGetAWSCredentials(SettingsStore.PSDefaultSettingName, ProfileLocation, out defaultAWSCredentials))
                {
                    awsPSCredentialsFromDefaultProfile = new AWSPSCredentials(defaultAWSCredentials, SettingsStore.PSDefaultSettingName, CredentialsSource.Profile);
                }
                else
                {
                    awsPSCredentialsFromDefaultProfile = null;
                }

                regionFromDefaultProfile = profile.Region;
            }
            else
            {
                awsPSCredentialsFromDefaultProfile = null;
                regionFromDefaultProfile           = null;
            }
        }
        protected override void ProcessRecord()
        {
            AWSPSCredentials currentCredentials = null;

            if (this.TryGetCredentials(Host, out currentCredentials, SessionState))
            {
                WriteVerbose(InitializeDefaultConfigurationCmdlet.CredentialsSourceMessage(currentCredentials));

                if (string.IsNullOrEmpty(StoreAs))
                {
                    SetUpIfFederatedCredentials(currentCredentials);
                    string scope = MyInvocation.BoundParameters.ContainsKey("Scope") ? Scope.ToString() + ":" : "";
                    this.SessionState.PSVariable.Set(scope + SessionKeys.AWSCredentialsVariableName, currentCredentials);
                }
                else
                {
                    if (MyInvocation.BoundParameters.ContainsKey("Scope"))
                    {
                        this.ThrowTerminatingError(new ErrorRecord(
                                                       new ArgumentException("Parameters Scope and StoreAs cannot be used together."),
                                                       "ArgumentException", ErrorCategory.InvalidArgument, this));
                    }

                    if (string.Equals(AWSCredentialsArgumentsFullCmdlet.AWSCredentialsObjectSet, ParameterSetName, StringComparison.Ordinal))
                    {
                        // We're storing from the -Credential parameter to a credentials file.
                        // Only some types of AWSCredentials are supported.
                        var options = CredentialProfileOptionsExtractor.ExtractProfileOptions(currentCredentials.Credentials);
                        if (options != null)
                        {
                            SettingsStore.RegisterProfile(options, StoreAs, ProfileLocation, null);
                        }
                    }
                    else
                    {
                        if (string.Equals(AWSCredentialsArgumentsFullCmdlet.StoredProfileSet, ParameterSetName, StringComparison.Ordinal))
                        {
                            // We're copying from one profile to another.
                            var chain = new CredentialProfileStoreChain(ProfileLocation);
                            CredentialProfile profile;
                            if (chain.TryGetProfile(ProfileName, out profile))
                            {
                                profile.CredentialProfileStore.CopyProfile(ProfileName, StoreAs, true);
                            }
                            else
                            {
                                // Parameters.TryGetCredentials has already tested for this but...
                                this.ThrowTerminatingError(new ErrorRecord(
                                                               new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                               "ArgumentException", ErrorCategory.InvalidArgument, this));
                            }
                        }
                        else
                        {
                            // We're storing from individual command line values to a credentials file.
                            SettingsStore.RegisterProfile(GetCredentialProfileOptions(), StoreAs, ProfileLocation, null);
                        }
                    }

                    if (string.IsNullOrEmpty(ProfileLocation))
                    {
                        WriteVerbose("Updated .NET credentials file.");
                    }
                    else
                    {
                        WriteVerbose("Updated shared credentials file at " + ProfileLocation);
                    }
                }
            }
            else
            {
                this.ThrowTerminatingError(new ErrorRecord(new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                           "ArgumentException",
                                                           ErrorCategory.InvalidArgument,
                                                           this));
            }
        }
        private string SelectAndStoreProfileForRole(IDictionary <string, string> availableRoles,
                                                    string preselectedRoleARN,
                                                    NetworkCredential networkCredential,
                                                    RegionEndpoint stsEndpointRegion)
        {
            var selectedRoleARN     = preselectedRoleARN;
            var roleSelectionNeeded = true;

            if (!string.IsNullOrEmpty(selectedRoleARN))
            {
                roleSelectionNeeded = !TestPreselectedRoleAvailable(selectedRoleARN, availableRoles.Values);
            }

            if (roleSelectionNeeded)
            {
                // if only one role, preselect
                if (availableRoles.Count == 1)
                {
                    selectedRoleARN = availableRoles.Values.First();
                    WriteVerbose(string.Format("Only one role available, pre-selecting role ARN {0}", preselectedRoleARN));
                }
                else
                {
                    var choices = new Collection <ChoiceDescription>();

                    // PowerShell labelling doesn't work if the shortcut is not in the label text (it
                    // adds it as extra text, which looks odd). Trying to select characters in the names
                    // can also be funky so the simplest approach is to manually prefix each role with an
                    // index number that is the shortcut. We used 1..9 on initial launch of this feature, then
                    // found a user with more than 10 roles so switched to alpha.
                    var shortcut = 'A';
                    foreach (var r in availableRoles.Keys)
                    {
                        string label = null;
                        if (shortcut <= 'Z')
                        {
                            label = string.Concat("&", shortcut++, " - ", r);
                        }
                        else
                        {
                            label = r;
                        }

                        choices.Add(new ChoiceDescription(label, availableRoles[r]));
                    }

                    var choice = Host.UI.PromptForChoice("Select Role", RolePrompt, choices, 0);
                    selectedRoleARN = choices[choice].HelpMessage;
                }
            }

            if (string.IsNullOrEmpty(selectedRoleARN))
            {
                ThrowExecutionError("A role is required before the profile can be stored.", this);
            }

            WriteVerbose(string.Format("Saving to profile '{0}'.\r\nUse 'Set-AWSCredentials -ProfileName {0}' to load this profile and obtain temporary AWS credentials.", StoreAs));

            string domainUser = null;

            if (networkCredential != null)
            {
                // user identity can be expressed in domain\user or email@domain formats - so don't auto-format
                // to domain\user unless a domain is actually present (if we do, profile ends up with \user@domain
                // and the user needs to strip it out each time we demand the password)
                domainUser = string.IsNullOrEmpty(networkCredential.Domain)
                    ? networkCredential.UserName
                    : string.Concat(networkCredential.Domain, "\\", networkCredential.UserName);
            }

            var options = new CredentialProfileOptions()
            {
                EndpointName = EndpointName,
                RoleArn      = selectedRoleARN,
                UserIdentity = domainUser
            };

            SettingsStore.RegisterProfile(options, StoreAs, null, stsEndpointRegion);

            return(StoreAs);
        }
        protected override void ProcessRecord()
        {
            try
            {
                string            selectedRoleARN   = null;
                NetworkCredential networkCredential = null;
                if (this.NetworkCredential != null)
                {
                    networkCredential = this.NetworkCredential.GetNetworkCredential();
                }

                var havePrincipal = ParameterWasBound("PrincipalARN");
                var haveRole      = ParameterWasBound("RoleARN");
                if (havePrincipal != haveRole)
                {
                    ThrowExecutionError("RoleARN must be specified with PrincipalARN.", this);
                }

                if (havePrincipal && haveRole)
                {
                    selectedRoleARN = string.Concat(PrincipalARN, ",", RoleARN);
                }

                WriteVerbose("Authenticating with endpoint to verify role data...");
                var samlEndpoint = (new SAMLEndpointManager()).GetEndpoint(EndpointName);

                var authenticationController = new SAMLAuthenticationController();

                var samlAssertion = authenticationController.GetSAMLAssertion(samlEndpoint.EndpointUri.ToString(),
                                                                              networkCredential, samlEndpoint.AuthenticationType.ToString());

                RegionEndpoint stsRegionEndpoint = null;
                if (!string.IsNullOrEmpty(STSEndpointRegion))
                {
                    stsRegionEndpoint = RegionEndpoint.GetBySystemName(STSEndpointRegion);
                }

                if (StoreAllRoles)
                {
                    string domainUser = null;
                    if (networkCredential != null)
                    {
                        // some credentials are entered in email format, so do not assume a domain
                        // was present
                        if (string.IsNullOrEmpty(networkCredential.Domain))
                        {
                            domainUser = networkCredential.UserName;
                        }
                        else
                        {
                            domainUser = string.Format(@"{0}\{1}", networkCredential.Domain, networkCredential.UserName);
                        }
                    }

                    var availableRoles = samlAssertion.RoleSet;
                    foreach (var roleName in availableRoles.Keys)
                    {
                        selectedRoleARN = availableRoles[roleName];
                        WriteVerbose(string.Format("Saving role '{0}' to profile '{1}'.", selectedRoleARN, roleName));

                        var options = new CredentialProfileOptions()
                        {
                            EndpointName = EndpointName,
                            RoleArn      = selectedRoleARN,
                            UserIdentity = domainUser
                        };
                        SettingsStore.RegisterProfile(options, roleName, null, stsRegionEndpoint);

                        WriteObject(roleName);
                    }
                }
                else
                {
                    var profileName = SelectAndStoreProfileForRole(samlAssertion.RoleSet, selectedRoleARN, networkCredential, stsRegionEndpoint);
                    WriteObject(profileName);
                }
            }
            catch (Exception e)
            {
                this.ThrowTerminatingError(new ErrorRecord(new ArgumentException("Unable to set credentials: " + e.Message, e),
                                                           "ArgumentException",
                                                           ErrorCategory.InvalidArgument,
                                                           this));
            }
        }
        protected override void ProcessRecord()
        {
            AWSPSCredentials awsPSCredentialsFromCommandLine;
            RegionEndpoint   regionFromCommandLine;
            AWSPSCredentials awsPSCredentialsFromDefaultProfile;
            RegionEndpoint   regionFromDefaultProfile;
            AWSPSCredentials awsPSCredentialsFromPromptingUser = null;
            RegionEndpoint   regionFromPromptingUser           = null;

            // get what was passed in on the command line, and what's already in defaults
            GetFromCommandLine(out awsPSCredentialsFromCommandLine, out regionFromCommandLine);
            GetFromDefaultProfile(out awsPSCredentialsFromDefaultProfile, out regionFromDefaultProfile);

            // if the command line and defaults don't provide us what we need then prompt the user
            if (awsPSCredentialsFromCommandLine == null && awsPSCredentialsFromDefaultProfile == null)
            {
                awsPSCredentialsFromPromptingUser = PromptUserForCredentials();
            }

            if (regionFromCommandLine == null && regionFromDefaultProfile == null)
            {
                regionFromPromptingUser = PromptUserForRegion();
            }

            // figure out what needs to be saved to disk and what needs to get put in session
            var awsPSCredentialsToPersist      = awsPSCredentialsFromCommandLine == null ? awsPSCredentialsFromPromptingUser : awsPSCredentialsFromCommandLine;
            var awsPSCredentialsToPutInSession = awsPSCredentialsToPersist == null ? awsPSCredentialsFromDefaultProfile : awsPSCredentialsToPersist;

            var regionToPersist      = regionFromCommandLine == null ? regionFromPromptingUser : regionFromCommandLine;
            var regionToPutInSession = regionToPersist == null ? regionFromDefaultProfile : regionToPersist;

            // save credentials and region to disk if necessary
            if (awsPSCredentialsToPersist != null || regionToPersist != null)
            {
                if (string.Equals(AWSCredentialsArgumentsFullCmdlet.AWSCredentialsObjectSet, ParameterSetName, StringComparison.Ordinal))
                {
                    // We're storing from the -Credential parameter to a credentials file.
                    // Only some types of AWSCredentials are supported.
                    var options = CredentialProfileOptionsExtractor.ExtractProfileOptions(awsPSCredentialsToPersist.Credentials);
                    if (options != null)
                    {
                        SettingsStore.RegisterProfile(options, SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                    }
                }
                else
                {
                    if (string.Equals(AWSCredentialsArgumentsFullCmdlet.StoredProfileSet, ParameterSetName, StringComparison.Ordinal))
                    {
                        // We're copying from one profile to another.
                        var chain = new CredentialProfileStoreChain(ProfileLocation);
                        CredentialProfile profile;
                        if (chain.TryGetProfile(ProfileName, out profile))
                        {
                            profile.CredentialProfileStore.CopyProfile(ProfileName, SettingsStore.PSDefaultSettingName, true);
                            SettingsStore.RegisterProfile(new CredentialProfileOptions(), SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                        }
                        else
                        {
                            // Parameters.TryGetCredentials has already tested for this but...
                            this.ThrowTerminatingError(new ErrorRecord(
                                                           new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                           "ArgumentException", ErrorCategory.InvalidArgument, this));
                        }
                    }
                    else
                    {
                        // We're storing from individual command line values to the default profile.
                        SettingsStore.RegisterProfile(GetCredentialProfileOptions(), SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                    }
                }

                if (string.IsNullOrEmpty(ProfileLocation))
                {
                    WriteVerbose("Updated SDK profile store.");
                }
                else
                {
                    WriteVerbose("Updated credential file at " + ProfileLocation);
                }
                WriteVerbose(string.Format("Default credentials and/or region have been stored to credentials profile '{0}' and set active for this shell.", SettingsStore.PSDefaultSettingName));
            }

            string scope = MyInvocation.BoundParameters.ContainsKey("Scope") ? Scope.ToString() + ":" : "";

            // put credentials and region in session
            this.SessionState.PSVariable.Set(scope + SessionKeys.AWSCredentialsVariableName, awsPSCredentialsToPutInSession);
            this.SessionState.PSVariable.Set(scope + SessionKeys.AWSRegionVariableName, regionToPutInSession.SystemName);
        }