private StoredInfo SelectAndStoreProfileForRole(string assertion, IList <SAMLCredential> roleSet, string preselectedPrincipalAndRoleARN)
        {
            string roleArn = preselectedPrincipalAndRoleARN;

            if (!this.TestPreselectedRoleAvailable(preselectedPrincipalAndRoleARN, roleSet.Select(arn => arn.Value).ToList()))
            {
                if (roleSet.Count == 1)
                {
                    roleArn = roleSet.First().Value;
                    base.WriteVerbose($"Only one role available, pre-selecting role ARN {preselectedPrincipalAndRoleARN}");
                }
                else
                {
                    if (AwsAccountId != null && AwsAccountId.Length > 0)
                    {
                        roleSet = roleSet.Where(r => AwsAccountId.Contains(r.PrincipalArn.AccountId, StringComparer.OrdinalIgnoreCase)).ToList();
                    }

                    var         width   = this.Host.UI.RawUI.WindowSize.Width - 4; // $MenuOptions.MaxWidth - 4
                    List <char> okchars = new List <char>();
                    for (char c = 'A'; c <= 'Z'; c++)
                    {
                        okchars.Add(c);                               // A - Z
                    }
                    for (char c = '0'; c <= '9'; c++)
                    {
                        okchars.Add(c);                               // 0 - 9
                    }
                    for (char c = '!'; c <= '/'; c++)
                    {
                        okchars.Add(c);                               // ! - /
                    }
                    for (char c = ':'; c <= '>'; c++)
                    {
                        okchars.Add(c);                               // : - >
                    }
                    for (char c = '['; c <= '_'; c++)
                    {
                        okchars.Add(c);                               // [ - _
                    }
                    for (char c = '{'; c <= '~'; c++)
                    {
                        okchars.Add(c);                               // { - ~
                    }
                    Collection <ChoiceDescription> collection = new Collection <ChoiceDescription>();
                    int idx = 0;
                    foreach (var cred in roleSet.OrderBy(r => r.RoleArn.AccountId).ThenBy(r => r.RoleArn.Resource))
                    {
                        string label;
                        if (roleSet.Count <= okchars.Count)
                        {
                            label = $"&{okchars[idx]} - {cred.RoleArn.Resource}";
                            label = NewSpaceDelimitedText(label, width) + ".";
                        }
                        else
                        {
                            label = cred.RoleArn.Resource;
                        }

                        collection.Add(new ChoiceDescription(label, cred.Value));
                        idx++;
                    }

                    bool userChooses = true;
                    int  idxDefault  = 0;
                    if (!string.IsNullOrWhiteSpace(this.HelpFindResource))
                    {
                        var fnd = collection.Where(r => r.Label.IndexOf(this.HelpFindResource, StringComparison.InvariantCultureIgnoreCase) >= 0).ToArray();
                        if (fnd.Length == 1 && this.SingleMatch)
                        {
                            WriteVerbose($"Found single match of role with the value '{this.HelpFindResource}', using that specific role only.");
                            roleArn     = collection[collection.IndexOf(fnd[0])].HelpMessage;
                            userChooses = false;
                        }
                        else if (fnd.Length >= 1)
                        {
                            idxDefault = collection.IndexOf(fnd[0]); // Pre-select the first role found with the HelpFindResource's value
                        }
                    }
                    if (userChooses)
                    {
                        int index = base.Host.UI.PromptForChoice(Lang.SelectRoleCaption, Lang.SelectRoleMessage, collection, idxDefault);
                        roleArn = collection[index].HelpMessage;
                    }
                }
            }
            if (string.IsNullOrEmpty(roleArn))
            {
                this.ThrowExecutionError(Lang.ErrorNoRoleSelected, this);
            }

            var role = roleSet.FirstOrDefault(r => r.Value.Equals(roleArn, StringComparison.OrdinalIgnoreCase));

            this.WriteVerbose($"Getting [{role.PrincipalArn}] tokens using [{role.RoleArn}]");
            var aRole = this.ExecuteCmdletInPipeline <dynamic>("Use-STSRoleWithSAML", new
            {
                SAMLAssertion     = assertion,
                RoleArn           = role.RoleArn.OriginalString,
                PrincipalArn      = role.PrincipalArn.OriginalString,
                DurationInSeconds = 60 * TokenDurationInMinutes
            }).FirstOrDefault();

            base.WriteVerbose($"Saving to profile '{this.StoreAs ?? role.RoleArn.Resource}'.");

            var home = this.GetVariableValue("HOME") as string;

            _ = this.ExecuteCmdletInPipeline("Set-AWSCredential", new
            {
                ProfileLocation = Path.Combine(home, ".aws", "credentials"),
                AccessKey       = aRole.Credentials.AccessKeyId,
                SecretKey       = aRole.Credentials.SecretAccessKey,
                aRole.Credentials.SessionToken,
                StoreAs = this.StoreAs ?? role.RoleArn.Resource
            });

            base.WriteVerbose($"Stored AWS Credentials as {this.StoreAs ?? role.RoleArn.Resource}.\r\nUse 'Set-AWSCredentials -ProfileName {this.StoreAs ?? role.RoleArn.Resource}' to load this profile and obtain temporary AWS credentials.");

            return(new StoredInfo {
                AssertionDoc = assertion,
                Expires = aRole.Credentials.Expiration,
                PrincipalArn = role.PrincipalArn,
                RoleArn = role.RoleArn,
                StoreAs = this.StoreAs ?? role.RoleArn.Resource
            });
        }
Beispiel #2
0
        protected override void ProcessRecord()
        {
            try
            {
                NetworkCredential networkCredential = null;
                if (this.Credential != null)
                {
                    base.WriteVerbose(Lang.UseGivenNetworkCredentials);
                    networkCredential = this.Credential.GetNetworkCredential();
                }

                ServicePointManager.SecurityProtocol = this.SecurityProtocol;
                IbmIam2AwsSamlScreenScrape aad2Aws = new IbmIam2AwsSamlScreenScrape(this)
                {
                    ErrorClass   = this.ErrorClass,
                    ErrorElement = this.ErrorElement,
                    Proxy        = this.GetWebProxy(),
                    Credentials  = networkCredential,
                    Logger       = (m, t) =>
                    {
                        switch (t)
                        {
                        case LogType.Debug:
                            this.WriteVerbose(m);
                            break;

                        case LogType.Info:
                            this.Host.UI.WriteLine(m);
                            //_cmdlet.WriteInformation(new InformationRecord(m, ""));
                            break;

                        case LogType.Warning:
                            this.WriteWarning(m);
                            break;

                        case LogType.Error:
                            this.WriteError(new ErrorRecord(new Exception(m), "5000", ErrorCategory.NotSpecified, this));
                            break;
                        }
                    }
                };

                var assertion = aad2Aws.RetrieveSAMLAssertion(IbmIamEndpoint);
                var roles     = aad2Aws.GetRolesFromAssertion();

                if (AwsAccountId != null && AwsAccountId.Length > 0)
                {
                    roles = roles.Where(r => AwsAccountId.Contains(r.PrincipalArn.AccountId, StringComparer.OrdinalIgnoreCase)).ToArray();
                }


                foreach (var role in roles)
                {
                    this.WriteObject(role);
                }
            }
            catch (IbmIamErrorException ex)
            {
                base.WriteError(new ErrorRecord(ex, ex.ErrorCode, ErrorCategory.NotSpecified, this));
            }
            catch (IbmIamPasswordExpiredException ex)
            {
                base.WriteError(new ErrorRecord(ex, "PasswordExpired", ErrorCategory.AuthenticationError, this));
            }
            catch (Exception ex)
            {
                base.WriteError(new ErrorRecord(new ArgumentException(string.Format(CultureInfo.CurrentCulture, Lang.ErrorUnableSetCredentials, ex.Message), ex), "ArgumentException", ErrorCategory.InvalidArgument, this));
            }
        }
        protected override void ProcessRecord()
        {
            try
            {
                string            preselectedPrincipalAndRoleARN = null;
                NetworkCredential networkCredential = null;
                if (this.Credential != null)
                {
                    base.WriteVerbose(Lang.UseGivenNetworkCredentials);
                    networkCredential = this.Credential.GetNetworkCredential();
                }
                bool hasPrinARN = this.ParameterWasBound(nameof(PrincipalARN)) && !string.IsNullOrWhiteSpace(this.PrincipalARN);
                bool hasRoleARN = this.ParameterWasBound(nameof(RoleARN)) && !string.IsNullOrWhiteSpace(this.RoleARN);
                if (hasPrinARN != hasRoleARN)
                {
                    this.ThrowExecutionError(Lang.PrincipalRequiredWithRole, this);
                }
                if (hasPrinARN & hasRoleARN)
                {
                    preselectedPrincipalAndRoleARN = $"{this.RoleARN},{this.PrincipalARN}";
                }

                ServicePointManager.SecurityProtocol = this.SecurityProtocol;
                IbmIam2AwsSamlScreenScrape ibm2Aws = new IbmIam2AwsSamlScreenScrape(this)
                {
                    ErrorClass   = this.ErrorClass,
                    ErrorElement = this.ErrorElement,
                    Proxy        = this.GetWebProxy(),
                    Credentials  = networkCredential,
                    Logger       = (m, t) =>
                    {
                        switch (t)
                        {
                        case LogType.Debug:
                            this.WriteVerbose(m);
                            break;

                        case LogType.Info:
                            this.Host.UI.WriteLine(m);
                            //_cmdlet.WriteInformation(new InformationRecord(m, ""));
                            break;

                        case LogType.Warning:
                            this.WriteWarning(m);
                            break;

                        case LogType.Error:
                            this.WriteError(new ErrorRecord(new Exception(m), "5000", ErrorCategory.NotSpecified, this));
                            break;
                        }
                    }
                };

                var assertion = ibm2Aws.RetrieveSAMLAssertion(IbmIamEndpoint);
                var roles     = ibm2Aws.GetRolesFromAssertion();

                if (this.StoreAllRoles)
                {
                    if (AwsAccountId != null && AwsAccountId.Length > 0)
                    {
                        roles = roles.Where(r => AwsAccountId.Contains(r.PrincipalArn.AccountId, StringComparer.OrdinalIgnoreCase)).ToArray();
                    }

                    foreach (var role in roles)
                    {
                        this.WriteVerbose($"Getting [{role.PrincipalArn}] tokens using [{role.RoleArn}]");
                        try
                        {
                            var aRole = this.ExecuteCmdletInPipeline <dynamic>("Use-STSRoleWithSAML", new
                            {
                                SAMLAssertion     = ibm2Aws.Assertion,
                                RoleArn           = role.RoleArn.OriginalString,
                                PrincipalArn      = role.PrincipalArn.OriginalString,
                                DurationInSeconds = 60 * this.TokenDurationInMinutes
                            }).FirstOrDefault();
                            this.WriteObject(new StoredInfo
                            {
                                AssertionDoc = assertion,
                                Expires      = aRole.Credentials.Expiration,
                                PrincipalArn = role.PrincipalArn,
                                RoleArn      = role.RoleArn,
                                StoreAs      = this.StoreAs ?? role.RoleArn.Resource
                            });
                            base.WriteVerbose($"Saving role '{role.Value}' to profile '{role.RoleArn.Resource}'.");
                            var home = this.GetVariableValue("HOME") as string;
                            _ = this.ExecuteCmdletInPipeline("Set-AWSCredential", new
                            {
                                ProfileLocation = Path.Combine(home, ".aws", "credentials"),
                                AccessKey       = aRole.Credentials.AccessKeyId,
                                SecretKey       = aRole.Credentials.SecretAccessKey,
                                aRole.Credentials.SessionToken,
                                StoreAs = role.RoleArn.Resource
                            });
                        }
                        //catch (ExpiredTokenException ex)
                        //{
                        //    this.WriteVerbose($"Could not Assume Role: {role.RoleArn.Resource}");
                        //    this.WriteVerbose("Attempting to Refresh Token");
                        //    // Updating Assertion Document
                        //    sAMLAssertion = _awsAuthController.GetSAMLAssertion(endpoint.EndpointUri.ToString(), networkCredential, endpoint.AuthenticationType.ToString());
                        //    this.WriteVerbose("Retrying this operation");
                        //    creds = AssumeRole(sts, config, role.RoleArn.Resource, sAMLAssertion, role, this.TokenDurationInMinutes);
                        //    this.WriteVerbose($"RetryResult: {creds}");
                        //}
                        catch (Exception ex)
                        {
                            this.WriteError(new ErrorRecord(ex, "5000", ErrorCategory.NotSpecified, this));
                        }
                    }
                }
                else
                {
                    StoredInfo sendToPipeline = this.SelectAndStoreProfileForRole(assertion, roles, preselectedPrincipalAndRoleARN);
                    base.WriteObject(sendToPipeline);
                }
            }
            catch (IbmIamErrorException ex)
            {
                base.WriteError(new ErrorRecord(ex, ex.ErrorCode, ErrorCategory.NotSpecified, this));
            }
            catch (IbmIamPasswordExpiredException ex)
            {
                base.WriteError(new ErrorRecord(ex, "PasswordExpired", ErrorCategory.AuthenticationError, this));
            }
            catch (Exception ex)
            {
                base.WriteError(new ErrorRecord(new ArgumentException("Unable to set credentials: " + ex.Message, ex), "ArgumentException", ErrorCategory.InvalidArgument, this));
            }
        }