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

SQL Server input plugin - Enable Azure Active Directory (AAD) authentication support #8822

Merged
merged 48 commits into from
Apr 21, 2021
Merged
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8d61ca4
Merge pull request #1 from influxdata/master
avinash-nigam Oct 29, 2020
c1da232
draft version to support aad auth for connecting to sql server instances
avinash-nigam Jan 8, 2021
33d2846
fixed aad token retrieval for sql databases and other code cleanup
avinash-nigam Feb 2, 2021
2d3c9d4
Merge remote-tracking branch 'upstream/master' into master
avinash-nigam Feb 7, 2021
db29456
Merge branch 'master' into sqlserver-aad-supp
avinash-nigam Feb 17, 2021
b2a7a7e
fixed circleci checks related errors
avinash-nigam Feb 17, 2021
2b137dc
addressed review comments for readme text, regex use, conditional che…
avinash-nigam Feb 20, 2021
fa20a2c
updated license of dependencies file to mention a license at a partic…
avinash-nigam Feb 20, 2021
3825cbf
added adal token cache mechanism, updated connection string regex and…
avinash-nigam Mar 22, 2021
66f899e
Merge remote-tracking branch 'upstream/master' into master
avinash-nigam Mar 22, 2021
5badf9d
draft version to support aad auth for connecting to sql server instances
avinash-nigam Jan 8, 2021
578076b
fixed aad token retrieval for sql databases and other code cleanup
avinash-nigam Feb 2, 2021
e347ae3
fixed circleci checks related errors
avinash-nigam Feb 17, 2021
70d0683
addressed review comments for readme text, regex use, conditional che…
avinash-nigam Feb 20, 2021
b492a9b
updated license of dependencies file to mention a license at a partic…
avinash-nigam Feb 20, 2021
9a846ba
added adal token cache mechanism, updated connection string regex and…
avinash-nigam Mar 22, 2021
9a37a10
Merge branch 'sqlserver-aad-supp' of https://github.com/avinash-nigam…
avinash-nigam Mar 22, 2021
2e0bace
fixed rebase/merge related errors
avinash-nigam Mar 22, 2021
80189c9
fixed lint related errors
avinash-nigam Mar 23, 2021
a7d3864
updated condition used to decide applicability of aad auth
avinash-nigam Mar 23, 2021
ca85285
tidying up go.sum for ci errors
avinash-nigam Mar 23, 2021
f4ccfe6
Merge branch 'master' into sqlserver-aad-supp
avinash-nigam Mar 23, 2021
8b93a36
more tidying up changes for go.mod and go.sum for ci error
avinash-nigam Mar 23, 2021
edd5a2b
minor correction in readme and mod changes based on golang version
avinash-nigam Mar 23, 2021
35834c1
Merge branch 'master' into sqlserver-aad-supp
avinash-nigam Mar 24, 2021
e231ccc
corrected condition used to decide auth mechanism applicability
avinash-nigam Mar 25, 2021
faf17d3
Merge remote-tracking branch 'upstream/master' into master
avinash-nigam Apr 1, 2021
559aa1d
draft version to support aad auth for connecting to sql server instances
avinash-nigam Jan 8, 2021
71dfa00
fixed aad token retrieval for sql databases and other code cleanup
avinash-nigam Feb 2, 2021
d1701d7
fixed circleci checks related errors
avinash-nigam Feb 17, 2021
3523ef5
addressed review comments for readme text, regex use, conditional che…
avinash-nigam Feb 20, 2021
223d4dc
updated license of dependencies file to mention a license at a partic…
avinash-nigam Feb 20, 2021
959106b
added adal token cache mechanism, updated connection string regex and…
avinash-nigam Mar 22, 2021
5e44105
draft version to support aad auth for connecting to sql server instances
avinash-nigam Jan 8, 2021
00d2f2a
fixed circleci checks related errors
avinash-nigam Feb 17, 2021
1605b81
addressed review comments for readme text, regex use, conditional che…
avinash-nigam Feb 20, 2021
10b0934
updated license of dependencies file to mention a license at a partic…
avinash-nigam Feb 20, 2021
233fa33
fixed rebase/merge related errors
avinash-nigam Mar 22, 2021
c49a11e
fixed lint related errors
avinash-nigam Mar 23, 2021
4a4f3ab
tidying up go.sum for ci errors
avinash-nigam Mar 23, 2021
65ad5cb
minor correction in readme and mod changes based on golang version
avinash-nigam Mar 23, 2021
62b542b
corrected condition used to decide auth mechanism applicability
avinash-nigam Mar 25, 2021
3fe7957
rebase master and corresponding changes
avinash-nigam Apr 1, 2021
2a9715e
Merge branch 'sqlserver-aad-supp' of https://github.com/avinash-nigam…
avinash-nigam Apr 1, 2021
ab34a7a
corrected errors induced during rebasing master
avinash-nigam Apr 1, 2021
92dccdb
addressed review comments related to leaking lock and other code cleanup
avinash-nigam Apr 14, 2021
4ae6774
Update to include suggestion for if with initialization stmt
avinash-nigam Apr 14, 2021
351fc91
small changes to add a comment and naming convention to address revie…
avinash-nigam Apr 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
71 changes: 33 additions & 38 deletions plugins/inputs/sqlserver/sqlserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sqlserver

import (
"database/sql"
"errors"
"fmt"
"log"
"regexp"
Expand All @@ -26,6 +27,8 @@ type SQLServer struct {
HealthMetric bool `toml:"health_metric"`
pools []*sql.DB
queries MapQuery
adalToken *adal.Token
muCacheLock sync.RWMutex
}

// Query struct
Expand All @@ -36,12 +39,6 @@ type Query struct {
OrderedColumns []string
}

// var to cache ADAL MSI token
var adalToken *adal.Token

// var for mutual exclusion lock
var muCacheLock sync.RWMutex

// MapQuery type
type MapQuery map[string]Query

Expand All @@ -68,6 +65,9 @@ const (
healthMetricDatabaseType = "database_type"
)

// resource id for Azure SQL Database
const sqlAzureResourceID = "https://database.windows.net/"

const sampleConfig = `
## Specify instances to monitor with a list of connection strings.
## All connection parameters are optional.
Expand Down Expand Up @@ -281,7 +281,7 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
}

// initialize mutual exclusion lock
muCacheLock = sync.RWMutex{}
s.muCacheLock = sync.RWMutex{}

for _, serv := range s.Servers {
var pool *sql.DB
Expand All @@ -296,29 +296,29 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {

avinash-nigam marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
acc.AddError(err)
return err
continue
}
} else {
// otherwise assume AAD Auth with system-assigned managed identity (MSI)

// AAD Auth is only supported for Azure SQL Database or Azure SQL Managed Instance
if s.DatabaseType == "SQLServer" {
return fmt.Errorf("Database connection failed : AAD auth is not supported for SQL VM i.e. DatabaseType=SQLServer")
er := errors.New("database connection failed : AAD auth is not supported for SQL VM i.e. DatabaseType=SQLServer")
acc.AddError(er)
avinash-nigam marked this conversation as resolved.
Show resolved Hide resolved
continue
}

// get token from im-memory cache variable or from Azure Active Directory
tokenProvider, err := getTokenProvider()
// get token from in-memory cache variable or from Azure Active Directory
tokenProvider, err := s.getTokenProvider()
if err != nil {
fmt.Printf("Error creating AAD token provider for system assigned Azure managed identity : %s", err.Error())
acc.AddError(err)
return err
acc.AddError(fmt.Errorf("error creating AAD token provider for system assigned Azure managed identity : %s", err.Error()))
continue
}

connector, err := mssql.NewAccessTokenConnector(serv, tokenProvider)
if err != nil {
fmt.Printf("Error creating the SQL connector : %s", err.Error())
acc.AddError(err)
return err
acc.AddError(fmt.Errorf("error creating the SQL connector : %s", err.Error()))
continue
}

pool = sql.OpenDB(connector)
Expand All @@ -341,8 +341,7 @@ func (s *SQLServer) gatherServer(pool *sql.DB, query Query, acc telegraf.Accumul
// execute query
rows, err := pool.Query(query.Script)
if err != nil {
return fmt.Errorf("Script %s failed: %w", query.ScriptName, err)
//return err
return fmt.Errorf("script %s failed: %w", query.ScriptName, err)
}
defer rows.Close()

Expand Down Expand Up @@ -465,26 +464,27 @@ func (s *SQLServer) Init() error {
}

// Get Token Provider by loading cached token or refreshed token
func getTokenProvider() (func() (string, error), error) {
func (s *SQLServer) getTokenProvider() (func() (string, error), error) {
avinash-nigam marked this conversation as resolved.
Show resolved Hide resolved
var tokenString string

// load token
muCacheLock.RLock()
token, err := loadToken()
muCacheLock.RUnlock()
s.muCacheLock.RLock()
token, err := s.loadToken()
s.muCacheLock.RUnlock()

// if there's error while loading token or found an expired token, refresh token and save it
if err != nil || token.IsExpired() {
// refresh token within a write-lock
muCacheLock.Lock()
s.muCacheLock.Lock()
defer s.muCacheLock.Unlock()

// load token again, in case it's been refreshed by another thread
token, err = loadToken()
token, err = s.loadToken()

// check loaded token's error/validity, then refresh/save token
if err != nil || token.IsExpired() {
// get new token
spt, err := refreshToken()
spt, err := s.refreshToken()
if err != nil {
return nil, err
}
Expand All @@ -495,8 +495,6 @@ func getTokenProvider() (func() (string, error), error) {
// use locally cached token
tokenString = token.OAuthToken()
}

muCacheLock.Unlock()
} else {
// use locally cached token
tokenString = token.OAuthToken()
Expand All @@ -509,19 +507,16 @@ func getTokenProvider() (func() (string, error), error) {
}

// Load token from in-mem cache
func loadToken() (*adal.Token, error) {
if adalToken == nil {
return nil, fmt.Errorf("Token is nil or Failed to load existing token")
func (s *SQLServer) loadToken() (*adal.Token, error) {
if s.adalToken == nil {
return nil, fmt.Errorf("token is nil or failed to load existing token")
}

return adalToken, nil
return s.adalToken, nil
}

// Refresh token for the resource, and save to in-mem cache
func refreshToken() (*adal.Token, error) {
// resource id for Azure SQL Database
const sqlAzureResourceID = "https://database.windows.net/"

func (s *SQLServer) refreshToken() (*adal.Token, error) {
// get MSI endpoint to get a token
msiEndpoint, err := adal.GetMSIVMEndpoint()
if err != nil {
Expand All @@ -541,7 +536,7 @@ func refreshToken() (*adal.Token, error) {
}

// save token to local in-mem cache
adalToken = &adal.Token{
s.adalToken = &adal.Token{
AccessToken: spt.Token().AccessToken,
RefreshToken: spt.Token().RefreshToken,
ExpiresIn: spt.Token().ExpiresIn,
Expand All @@ -551,7 +546,7 @@ func refreshToken() (*adal.Token, error) {
Type: spt.Token().Type,
}

return adalToken, nil
return s.adalToken, nil
}

func init() {
Expand Down