github.com/versent/saml2aws@v2.17.0+incompatible/saml2aws.go (about) 1 package saml2aws 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/versent/saml2aws/pkg/cfg" 8 "github.com/versent/saml2aws/pkg/creds" 9 "github.com/versent/saml2aws/pkg/provider/aad" 10 "github.com/versent/saml2aws/pkg/provider/adfs" 11 "github.com/versent/saml2aws/pkg/provider/adfs2" 12 "github.com/versent/saml2aws/pkg/provider/f5apm" 13 "github.com/versent/saml2aws/pkg/provider/googleapps" 14 "github.com/versent/saml2aws/pkg/provider/jumpcloud" 15 "github.com/versent/saml2aws/pkg/provider/keycloak" 16 "github.com/versent/saml2aws/pkg/provider/okta" 17 "github.com/versent/saml2aws/pkg/provider/onelogin" 18 "github.com/versent/saml2aws/pkg/provider/pingfed" 19 "github.com/versent/saml2aws/pkg/provider/pingone" 20 "github.com/versent/saml2aws/pkg/provider/psu" 21 "github.com/versent/saml2aws/pkg/provider/shibboleth" 22 ) 23 24 // ProviderList list of providers with their MFAs 25 type ProviderList map[string][]string 26 27 // MFAsByProvider a list of providers with their respective supported MFAs 28 var MFAsByProvider = ProviderList{ 29 "AzureAD": []string{"Auto", "PhoneAppOTP", "PhoneAppNotification", "OneWaySMS"}, 30 "ADFS": []string{"Auto", "VIP"}, 31 "ADFS2": []string{"Auto", "RSA"}, // nothing automatic about ADFS 2.x 32 "Ping": []string{"Auto"}, // automatically detects PingID 33 "PingOne": []string{"Auto"}, // automatically detects PingID 34 "JumpCloud": []string{"Auto"}, 35 "Okta": []string{"Auto", "PUSH", "DUO", "SMS", "TOTP", "OKTA"}, // automatically detects DUO, SMS and ToTP 36 "OneLogin": []string{"Auto", "OLP", "SMS", "TOTP"}, // automatically detects OneLogin Protect, SMS and ToTP 37 "KeyCloak": []string{"Auto"}, // automatically detects ToTP 38 "GoogleApps": []string{"Auto"}, // automatically detects ToTP 39 "Shibboleth": []string{"Auto"}, 40 "PSU": []string{"Auto"}, 41 "F5APM": []string{"Auto"}, 42 } 43 44 // Names get a list of provider names 45 func (mfbp ProviderList) Names() []string { 46 keys := []string{} 47 for k := range mfbp { 48 keys = append(keys, k) 49 } 50 51 sort.Strings(keys) 52 53 return keys 54 } 55 56 // Mfas retrieve a sorted list of mfas from the provider list 57 func (mfbp ProviderList) Mfas(provider string) []string { 58 mfas := mfbp[provider] 59 60 sort.Strings(mfas) 61 62 return mfas 63 } 64 65 func (mfbp ProviderList) stringInSlice(a string, list []string) bool { 66 for _, b := range list { 67 if b == a { 68 return true 69 } 70 } 71 return false 72 } 73 74 func invalidMFA(provider string, mfa string) bool { 75 supportedMfas := MFAsByProvider.Mfas(provider) 76 return !MFAsByProvider.stringInSlice(mfa, supportedMfas) 77 } 78 79 // SAMLClient client interface 80 type SAMLClient interface { 81 Authenticate(loginDetails *creds.LoginDetails) (string, error) 82 } 83 84 // NewSAMLClient create a new SAML client 85 func NewSAMLClient(idpAccount *cfg.IDPAccount) (SAMLClient, error) { 86 switch idpAccount.Provider { 87 case "AzureAD": 88 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 89 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 90 } 91 return aad.New(idpAccount) 92 case "ADFS": 93 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 94 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 95 } 96 return adfs.New(idpAccount) 97 case "ADFS2": 98 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 99 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 100 } 101 return adfs2.New(idpAccount) 102 case "Ping": 103 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 104 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 105 } 106 return pingfed.New(idpAccount) 107 case "PingOne": 108 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 109 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 110 } 111 return pingone.New(idpAccount) 112 case "JumpCloud": 113 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 114 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 115 } 116 return jumpcloud.New(idpAccount) 117 case "Okta": 118 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 119 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 120 } 121 return okta.New(idpAccount) 122 case "OneLogin": 123 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 124 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 125 } 126 return onelogin.New(idpAccount) 127 case "KeyCloak": 128 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 129 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 130 } 131 return keycloak.New(idpAccount) 132 case "GoogleApps": 133 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 134 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 135 } 136 return googleapps.New(idpAccount) 137 case "Shibboleth": 138 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 139 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 140 } 141 return shibboleth.New(idpAccount) 142 case "PSU": 143 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 144 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 145 } 146 return psu.New(idpAccount) 147 case "F5APM": 148 if invalidMFA(idpAccount.Provider, idpAccount.MFA) { 149 return nil, fmt.Errorf("Invalid MFA type: %v for %v provider", idpAccount.MFA, idpAccount.Provider) 150 } 151 return f5apm.New(idpAccount) 152 153 default: 154 return nil, fmt.Errorf("Invalid provider: %v", idpAccount.Provider) 155 } 156 }