66 "fmt"
77 "math/big"
88 "net/mail"
9+ "strings"
910
1011 v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
1112 "github.com/conductorone/baton-sdk/pkg/annotations"
@@ -98,6 +99,7 @@ func (d *userPrincipalSyncer) CreateAccount(
9899 accountInfo * v2.AccountInfo ,
99100 credentialOptions * v2.CredentialOptions ,
100101) (connectorbuilder.CreateAccountResponse , []* v2.PlaintextData , annotations.Annotations , error ) {
102+ var domain , formattedUsername , password string
101103 l := ctxzap .Extract (ctx )
102104
103105 // Extract required login_type field from profile
@@ -115,43 +117,24 @@ func (d *userPrincipalSyncer) CreateAccount(
115117 }
116118 username := usernameVal .GetStringValue ()
117119
118- // Extract optional domain field (for Windows auth) or password (for SQL auth)
119- var domain , password string
120- var formattedUsername string
121-
122- switch loginType {
123- case mssqldb .LoginTypeWindows :
124- // For Windows auth, extract domain
125- domainVal := accountInfo .Profile .GetFields ()["domain" ]
126- if domainVal != nil && domainVal .GetStringValue () != "" {
127- domain = domainVal .GetStringValue ()
128- }
120+ domainVal := accountInfo .Profile .GetFields ()["domain" ]
121+ if domainVal != nil && domainVal .GetStringValue () != "" {
122+ domain = domainVal .GetStringValue ()
123+ }
129124
130- if domain != "" {
131- formattedUsername = fmt .Sprintf ("%s\\ %s" , domain , username )
132- } else {
133- formattedUsername = username
134- }
135- case mssqldb .LoginTypeSQL :
136- // For SQL auth, generate a strong random password
137- password = generateStrongPassword ()
138- l .Debug ("generated random password for SQL Server authentication" )
139- formattedUsername = username
140- case mssqldb .LoginTypeAzureAD , mssqldb .LoginTypeEntraID :
141- // For Azure AD or Entra ID, just use the username as is
142- formattedUsername = username
143- default :
144- return nil , nil , nil , fmt .Errorf ("unsupported login type: %s" , loginType )
125+ formattedUsername , password , err := formatUserLogin (ctx , loginType , username , domain )
126+ if err != nil {
127+ return nil , nil , nil , err
145128 }
146129
147130 // Create the login
148- err : = d .client .CreateLogin (ctx , loginType , domain , username , password )
131+ err = d .client .CreateLogin (ctx , loginType , formattedUsername , password )
149132 if err != nil {
150133 l .Error ("Failed to create login" , zap .Error (err ), zap .String ("loginType" , string (loginType )))
151134 return nil , nil , nil , fmt .Errorf ("failed to create login: %w" , err )
152135 }
153136
154- uid , err := d .client .GetUserPrincipalByName (ctx , username )
137+ uid , err := d .client .GetUserPrincipalByName (ctx , formattedUsername )
155138 if err != nil {
156139 return nil , nil , nil , fmt .Errorf ("failed to get user: %w" , err )
157140 }
@@ -211,6 +194,42 @@ func (d *userPrincipalSyncer) CreateAccount(
211194 return successResult , plaintextData , nil , nil
212195}
213196
197+ func formatUserLogin (ctx context.Context , loginType mssqldb.LoginType , username string , domain string ) (string , string , error ) {
198+ var formattedUsername , password string
199+ l := ctxzap .Extract (ctx )
200+
201+ // Check for invalid characters to prevent SQL injection
202+ if (domain != "" && strings .ContainsAny (domain , "[]\" ';" )) || strings .ContainsAny (username , "[]\" ';" ) {
203+ return "" , "" , fmt .Errorf ("invalid characters in domain or username" )
204+ }
205+
206+ switch loginType {
207+ case mssqldb .LoginTypeWindows :
208+ if domain != "" {
209+ formattedUsername = fmt .Sprintf ("%s\\ %s" , domain , username )
210+ l .Debug ("windows login will be created with domain" , zap .String ("login" , formattedUsername ))
211+ } else {
212+ formattedUsername = username
213+ l .Debug ("windows login will be created without domain" , zap .String ("login" , formattedUsername ))
214+ }
215+
216+ case mssqldb .LoginTypeSQL :
217+ // For SQL auth, generate a strong random password
218+ password = generateStrongPassword ()
219+ l .Debug ("generated random password for SQL Server authentication" )
220+ formattedUsername = username
221+
222+ case mssqldb .LoginTypeAzureAD , mssqldb .LoginTypeEntraID :
223+ // For Azure AD or Entra ID, just use the username as is
224+ formattedUsername = username
225+
226+ default :
227+ return "" , "" , fmt .Errorf ("unsupported login type: %s" , loginType )
228+ }
229+
230+ return formattedUsername , password , nil
231+ }
232+
214233// CreateAccountCapabilityDetails returns the capability details for account creation.
215234func (d * userPrincipalSyncer ) CreateAccountCapabilityDetails (
216235 ctx context.Context ,
0 commit comments