2016-03-03 14:19:17 +00:00
package mssql
import (
2018-01-08 18:31:38 +00:00
"context"
2016-03-03 14:19:17 +00:00
"database/sql"
"fmt"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/framework"
2016-03-03 14:19:17 +00:00
)
func pathConfigConnection ( b * backend ) * framework . Path {
return & framework . Path {
Pattern : "config/connection" ,
Fields : map [ string ] * framework . FieldSchema {
2016-03-10 04:08:05 +00:00
"connection_string" : & framework . FieldSchema {
2016-03-03 14:19:17 +00:00
Type : framework . TypeString ,
Description : "DB connection parameters" ,
} ,
"max_open_connections" : & framework . FieldSchema {
Type : framework . TypeInt ,
Description : "Maximum number of open connections to database" ,
} ,
2016-03-10 04:08:05 +00:00
"verify_connection" : & framework . FieldSchema {
Type : framework . TypeBool ,
Default : true ,
Description : "If set, connection_string is verified by actually connecting to the database" ,
} ,
2016-03-03 14:19:17 +00:00
} ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . UpdateOperation : b . pathConnectionWrite ,
2016-06-11 15:48:40 +00:00
logical . ReadOperation : b . pathConnectionRead ,
2016-03-03 14:19:17 +00:00
} ,
HelpSynopsis : pathConfigConnectionHelpSyn ,
HelpDescription : pathConfigConnectionHelpDesc ,
}
}
2016-06-17 14:11:39 +00:00
// pathConnectionRead reads out the connection configuration
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathConnectionRead ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2018-01-19 06:44:44 +00:00
entry , err := req . Storage . Get ( ctx , "config/connection" )
2016-06-11 15:48:40 +00:00
if err != nil {
return nil , fmt . Errorf ( "failed to read connection configuration" )
}
if entry == nil {
return nil , nil
}
var config connectionConfig
if err := entry . DecodeJSON ( & config ) ; err != nil {
return nil , err
}
2018-03-30 14:17:39 +00:00
2016-06-11 15:48:40 +00:00
return & logical . Response {
2018-03-30 14:17:39 +00:00
Data : map [ string ] interface { } {
"max_open_connections" : config . MaxOpenConnections ,
} ,
2016-06-11 15:48:40 +00:00
} , nil
}
// pathConnectionWrite stores the connection configuration
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathConnectionWrite ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2016-03-10 04:08:05 +00:00
connString := data . Get ( "connection_string" ) . ( string )
2016-03-03 14:19:17 +00:00
maxOpenConns := data . Get ( "max_open_connections" ) . ( int )
if maxOpenConns == 0 {
maxOpenConns = 2
}
2016-03-10 04:08:05 +00:00
// Don't check the connection_string if verification is disabled
verifyConnection := data . Get ( "verify_connection" ) . ( bool )
if verifyConnection {
// Verify the string
db , err := sql . Open ( "mssql" , connString )
2016-03-03 14:19:17 +00:00
2016-03-10 04:08:05 +00:00
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf (
"Error validating connection info: %s" , err ) ) , nil
}
defer db . Close ( )
if err := db . Ping ( ) ; err != nil {
return logical . ErrorResponse ( fmt . Sprintf (
"Error validating connection info: %s" , err ) ) , nil
}
2016-03-03 14:19:17 +00:00
}
// Store it
entry , err := logical . StorageEntryJSON ( "config/connection" , connectionConfig {
2016-03-10 04:08:05 +00:00
ConnectionString : connString ,
2016-03-03 14:19:17 +00:00
MaxOpenConnections : maxOpenConns ,
} )
if err != nil {
return nil , err
}
2018-01-19 06:44:44 +00:00
if err := req . Storage . Put ( ctx , entry ) ; err != nil {
2016-03-03 14:19:17 +00:00
return nil , err
}
// Reset the DB connection
2018-01-19 06:44:44 +00:00
b . ResetDB ( ctx )
2016-06-21 13:58:57 +00:00
resp := & logical . Response { }
resp . AddWarning ( "Read access to this endpoint should be controlled via ACLs as it will return the connection string as it is, including passwords, if any." )
return resp , nil
2016-03-03 14:19:17 +00:00
}
type connectionConfig struct {
2016-06-11 15:48:40 +00:00
ConnectionString string ` json:"connection_string" structs:"connection_string" mapstructure:"connection_string" `
MaxOpenConnections int ` json:"max_open_connections" structs:"max_open_connections" mapstructure:"max_open_connections" `
2016-03-03 14:19:17 +00:00
}
const pathConfigConnectionHelpSyn = `
Configure the connection string to talk to Microsoft Sql Server .
`
const pathConfigConnectionHelpDesc = `
This path configures the connection string used to connect to Sql Server .
The value of the string is a Data Source Name ( DSN ) . An example is
2016-03-10 04:08:05 +00:00
using "server=<hostname>;port=<port>;user id=<username>;password=<password>;database=<database>;app name=vault;"
2016-03-03 14:19:17 +00:00
When configuring the connection string , the backend will verify its validity .
2016-03-10 04:08:05 +00:00
If the database is not available when setting the connection string , set the
"verify_connection" option to false .
2016-03-03 14:19:17 +00:00
`