github.com/versent/saml2aws@v2.17.0+incompatible/aws_account.go (about) 1 package saml2aws 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "net/http" 7 "net/url" 8 9 "fmt" 10 11 "github.com/PuerkitoBio/goquery" 12 "github.com/pkg/errors" 13 ) 14 15 const awsURL = "https://signin.aws.amazon.com/saml" 16 17 // AWSAccount holds the AWS account name and roles 18 type AWSAccount struct { 19 Name string 20 Roles []*AWSRole 21 } 22 23 // ParseAWSAccounts extract the aws accounts from the saml assertion 24 func ParseAWSAccounts(samlAssertion string) ([]*AWSAccount, error) { 25 26 res, err := http.PostForm(awsURL, url.Values{"SAMLResponse": {samlAssertion}}) 27 if err != nil { 28 return nil, errors.Wrap(err, "error retrieving AWS login form") 29 } 30 31 data, err := ioutil.ReadAll(res.Body) 32 if err != nil { 33 return nil, errors.Wrap(err, "error retrieving AWS login body") 34 } 35 36 return ExtractAWSAccounts(data) 37 } 38 39 // ExtractAWSAccounts extract the accounts from the AWS html page 40 func ExtractAWSAccounts(data []byte) ([]*AWSAccount, error) { 41 accounts := []*AWSAccount{} 42 43 doc, err := goquery.NewDocumentFromReader(bytes.NewBuffer(data)) 44 if err != nil { 45 return nil, errors.Wrap(err, "failed to build document from response") 46 } 47 48 doc.Find("fieldset > div.saml-account").Each(func(i int, s *goquery.Selection) { 49 account := new(AWSAccount) 50 account.Name = s.Find("div.saml-account-name").Text() 51 s.Find("label").Each(func(i int, s *goquery.Selection) { 52 role := new(AWSRole) 53 role.Name = s.Text() 54 role.RoleARN, _ = s.Attr("for") 55 account.Roles = append(account.Roles, role) 56 }) 57 accounts = append(accounts, account) 58 }) 59 60 return accounts, nil 61 } 62 63 // AssignPrincipals assign principal from roles 64 func AssignPrincipals(awsRoles []*AWSRole, awsAccounts []*AWSAccount) { 65 66 awsPrincipalARNs := make(map[string]string) 67 for _, awsRole := range awsRoles { 68 awsPrincipalARNs[awsRole.RoleARN] = awsRole.PrincipalARN 69 } 70 71 for _, awsAccount := range awsAccounts { 72 for _, awsRole := range awsAccount.Roles { 73 awsRole.PrincipalARN = awsPrincipalARNs[awsRole.RoleARN] 74 } 75 } 76 77 } 78 79 // LocateRole locate role by name 80 func LocateRole(awsRoles []*AWSRole, roleName string) (*AWSRole, error) { 81 for _, awsRole := range awsRoles { 82 if awsRole.RoleARN == roleName { 83 return awsRole, nil 84 } 85 } 86 87 return nil, fmt.Errorf("Supplied RoleArn not found in saml assertion: %s", roleName) 88 }