Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SqlServer MSI Support #591

Merged
merged 15 commits into from
Jul 2, 2021
Merged

Add SqlServer MSI Support #591

merged 15 commits into from
Jul 2, 2021

Conversation

samfoxcode
Copy link
Contributor

Add the option for MSI Auth to Azure SQL Server. Expects a param to be passed to enable MSI Auth, useMsi=true.

  • update go-mssqldb module to pull in msi auth support
  • make code change in database/sqlserver/sqlserver.go to check for useMsi param
  • dynamically get database resource uri based on the server uri
  • adds adal module which is needed for fetching the msi token

PR from denisenkom/go-mssqldb that added msi support: #546

samfoxcode and others added 12 commits June 16, 2021 14:42
Add MSI Auth option to SQL Server connection. Default if no password is provided in connection string.
update host name parsing to get just the resource endpoint for msi
update go-mssqldb to resolve panic issue referenced here: denisenkom/go-mssqldb#642
switch from deprecated methods. NewServicePrincipalTokenFromManagedIdentity calls the two methods that are deprecated for us
add useMsi param instead of looking for nil password
Update sqlserver readme for msi auth. make useMsi a bit safer
remove comment
refactor resource uri logic into its own method
add tests for msi connection. can only test whether it fails with useMsi= true, or succeeds with useMsi=false
check msi.EnsureFresh return value
@coveralls
Copy link

coveralls commented Jun 29, 2021

Pull Request Test Coverage Report for Build 487

  • 33 of 45 (73.33%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 57.324%

Changes Missing Coverage Covered Lines Changed/Added Lines %
database/sqlserver/sqlserver.go 33 45 73.33%
Totals Coverage Status
Change from base Build 468: 0.2%
Covered Lines: 3612
Relevant Lines: 6301

💛 - Coveralls

Copy link
Member

@dhui dhui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

}

connector, err := mssql.NewAccessTokenConnector(
migrate.FilterCustomQuery(purl).String(), tokenProvider)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factor out migrate.FilterCustomQuery(purl).String() to prevent accidental divergence in the future.
e.g. filteredURL := migrate.FilterCustomQuery(purl).String()

addr := msConnectionStringMsi(ip, port, true)
p := &SQLServer{}
_, err = p.Open(addr)
if err == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anyway to test the success case? e.g. are there mock providers available as docker images?

I'm happy to merge this in without the happy case tests but can't provide official support unless there are sufficient tests. e.g. w/o the happy case test, you'll need to mark this parameter as not officially supported in the README

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't seem to be a way to mock this through container images. The SQL Server container docs only go through password auth and don't mentioned MSI/AAD auth, which kinda makes sense since they're native to Azure, but would be nice if they provided mock images to test auth. We could mock MSI auth in code by returning an empty token, but that would only work if we were mocking the SQL Server instance as well and could control the auth on both sides. For now I will add a disclaimer in the README saying it's not officially supported.

Also, we have tested the happypath manually in our own scenarios and it does work.

}

var db *sql.DB
if useMsi {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would we handle the case when both useMsi and a password are specified?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I think it makes sense to default to MSI auth and could then also log a message to the console saying something along the lines of "Both MSI Auth and Password Auth were requested, defaulting to MSI Auth. Password will be ignored" (can update the README with this behavior as well). Any sort of fallback to password auth should probably be handled by the caller.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any objections to making these options mutually exclusive? e.g. error if both are specified?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good to me, made the change.

move migrate.FilterCustomQuery(purl).String() into one line out of if/else. return error if both useMsi=true and password are passed
update readme with warning for useMsi
Update TestMsiFalse test case as now it should fail when useMsi=false and no password is provided
Copy link
Member

@dhui dhui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the prompt response!

ErrNoDatabaseName = fmt.Errorf("no database name")
ErrNoSchema = fmt.Errorf("no schema")
ErrDatabaseDirty = fmt.Errorf("database is dirty")
ErrMultipleAuthOptionsPassed = fmt.Errorf("both password and useMsi=true were passed.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making this a reference-able error!

@dhui dhui merged commit 805f8c8 into golang-migrate:master Jul 2, 2021
@samfoxcode
Copy link
Contributor Author

Thanks for the prompt response!

Thank you as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants