-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
path_config_connection.go
127 lines (107 loc) · 3.87 KB
/
path_config_connection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package mssql
import (
"context"
"database/sql"
"fmt"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
func pathConfigConnection(b *backend) *framework.Path {
return &framework.Path{
Pattern: "config/connection",
Fields: map[string]*framework.FieldSchema{
"connection_string": &framework.FieldSchema{
Type: framework.TypeString,
Description: "DB connection parameters",
},
"max_open_connections": &framework.FieldSchema{
Type: framework.TypeInt,
Description: "Maximum number of open connections to database",
},
"verify_connection": &framework.FieldSchema{
Type: framework.TypeBool,
Default: true,
Description: "If set, connection_string is verified by actually connecting to the database",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: b.pathConnectionWrite,
logical.ReadOperation: b.pathConnectionRead,
},
HelpSynopsis: pathConfigConnectionHelpSyn,
HelpDescription: pathConfigConnectionHelpDesc,
}
}
// pathConnectionRead reads out the connection configuration
func (b *backend) pathConnectionRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
entry, err := req.Storage.Get(ctx, "config/connection")
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
}
return &logical.Response{
Data: map[string]interface{}{
"max_open_connections": config.MaxOpenConnections,
},
}, nil
}
// pathConnectionWrite stores the connection configuration
func (b *backend) pathConnectionWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
connString := data.Get("connection_string").(string)
maxOpenConns := data.Get("max_open_connections").(int)
if maxOpenConns == 0 {
maxOpenConns = 2
}
// 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)
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
}
}
// Store it
entry, err := logical.StorageEntryJSON("config/connection", connectionConfig{
ConnectionString: connString,
MaxOpenConnections: maxOpenConns,
})
if err != nil {
return nil, err
}
if err := req.Storage.Put(ctx, entry); err != nil {
return nil, err
}
// Reset the DB connection
b.ResetDB(ctx)
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
}
type connectionConfig struct {
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"`
}
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
using "server=<hostname>;port=<port>;user id=<username>;password=<password>;database=<database>;app name=vault;"
When configuring the connection string, the backend will verify its validity.
If the database is not available when setting the connection string, set the
"verify_connection" option to false.
`