Merge branch 'master-oss' into postgres-pl-lock
This commit is contained in:
commit
f7a6515889
|
@ -26,6 +26,10 @@ IMPROVEMENTS:
|
|||
different paths using the command options [GH-1532]
|
||||
* cli: `vault auth -methods` will now display the config settings of the mount
|
||||
[GH-1531]
|
||||
* cli: `vault read/write/unwrap -field` now allows selecting token response
|
||||
fields [GH-1567]
|
||||
* cli: `vault write -field` now allows selecting wrapped response fields
|
||||
[GH-1567]
|
||||
* credential/aws-ec2: Added a new constraint, 'bound_account_id' to the role
|
||||
[GH-1523]
|
||||
* secret/aws: Listing of roles is supported now [GH-1546]
|
||||
|
@ -38,6 +42,8 @@ BUG FIXES:
|
|||
during renewal [GH-1542]
|
||||
* core: Fix regression causing status codes to be `400` in most non-5xx error
|
||||
cases [GH-1553]
|
||||
* physical/postgres: Remove use of prepared statements as this causes
|
||||
connection multiplexing software to break [GH-1548]
|
||||
|
||||
## 0.6.0 (June 14th, 2016)
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ func TestServer_ReloadListener(t *testing.T) {
|
|||
}
|
||||
|
||||
checkFinished()
|
||||
time.Sleep(2 * time.Second)
|
||||
time.Sleep(5 * time.Second)
|
||||
checkFinished()
|
||||
|
||||
if err := testCertificateName("foo.example.com"); err != nil {
|
||||
|
|
|
@ -31,27 +31,44 @@ func DefaultTokenHelper() (token.TokenHelper, error) {
|
|||
|
||||
func PrintRawField(ui cli.Ui, secret *api.Secret, field string) int {
|
||||
var val interface{}
|
||||
switch field {
|
||||
case "wrapping_token":
|
||||
if secret.WrapInfo != nil {
|
||||
switch {
|
||||
case secret.Auth != nil:
|
||||
switch field {
|
||||
case "token":
|
||||
val = secret.Auth.ClientToken
|
||||
case "token_accessor":
|
||||
val = secret.Auth.Accessor
|
||||
case "token_duration":
|
||||
val = secret.Auth.LeaseDuration
|
||||
case "token_renewable":
|
||||
val = secret.Auth.Renewable
|
||||
case "token_policies":
|
||||
val = secret.Auth.Policies
|
||||
default:
|
||||
val = secret.Data[field]
|
||||
}
|
||||
|
||||
case secret.WrapInfo != nil:
|
||||
switch field {
|
||||
case "wrapping_token":
|
||||
val = secret.WrapInfo.Token
|
||||
}
|
||||
case "wrapping_token_ttl":
|
||||
if secret.WrapInfo != nil {
|
||||
case "wrapping_token_ttl":
|
||||
val = secret.WrapInfo.TTL
|
||||
}
|
||||
case "wrapping_token_creation_time":
|
||||
if secret.WrapInfo != nil {
|
||||
case "wrapping_token_creation_time":
|
||||
val = secret.WrapInfo.CreationTime.String()
|
||||
}
|
||||
case "wrapped_accessor":
|
||||
if secret.WrapInfo != nil {
|
||||
case "wrapped_accessor":
|
||||
val = secret.WrapInfo.WrappedAccessor
|
||||
default:
|
||||
val = secret.Data[field]
|
||||
}
|
||||
case "refresh_interval":
|
||||
val = secret.LeaseDuration
|
||||
|
||||
default:
|
||||
val = secret.Data[field]
|
||||
switch field {
|
||||
case "refresh_interval":
|
||||
val = secret.LeaseDuration
|
||||
default:
|
||||
val = secret.Data[field]
|
||||
}
|
||||
}
|
||||
|
||||
if val != nil {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/helper/kv-builder"
|
||||
|
@ -75,23 +74,7 @@ func (c *WriteCommand) Run(args []string) int {
|
|||
|
||||
// Handle single field output
|
||||
if field != "" {
|
||||
if val, ok := secret.Data[field]; ok {
|
||||
// c.Ui.Output() prints a CR character which in this case is
|
||||
// not desired. Since Vault CLI currently only uses BasicUi,
|
||||
// which writes to standard output, os.Stdout is used here to
|
||||
// directly print the message. If mitchellh/cli exposes method
|
||||
// to print without CR, this check needs to be removed.
|
||||
if reflect.TypeOf(c.Ui).String() == "*cli.BasicUi" {
|
||||
fmt.Fprintf(os.Stdout, fmt.Sprintf("%v", val))
|
||||
} else {
|
||||
c.Ui.Output(fmt.Sprintf("%v", val))
|
||||
}
|
||||
return 0
|
||||
} else {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Field %s not present in secret", field))
|
||||
return 1
|
||||
}
|
||||
return PrintRawField(c.Ui, secret, field)
|
||||
}
|
||||
|
||||
return OutputSecret(c.Ui, format, secret)
|
||||
|
|
|
@ -14,9 +14,12 @@ import (
|
|||
// PostgreSQL Backend is a physical backend that stores data
|
||||
// within a PostgreSQL database.
|
||||
type PostgreSQLBackend struct {
|
||||
table string
|
||||
client *sql.DB
|
||||
statements map[string]*sql.Stmt
|
||||
table string
|
||||
client *sql.DB
|
||||
put_query string
|
||||
get_query string
|
||||
delete_query string
|
||||
list_query string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
|
@ -50,49 +53,30 @@ func newPostgreSQLBackend(conf map[string]string, logger *log.Logger) (Backend,
|
|||
|
||||
// Setup our put strategy based on the presence or absence of a native
|
||||
// upsert.
|
||||
var put_statement string
|
||||
var put_query string
|
||||
if upsert_required {
|
||||
put_statement = "SELECT vault_kv_put($1, $2, $3, $4)"
|
||||
put_query = "SELECT vault_kv_put($1, $2, $3, $4)"
|
||||
} else {
|
||||
put_statement = "INSERT INTO " + quoted_table + " VALUES($1, $2, $3, $4)" +
|
||||
put_query = "INSERT INTO " + quoted_table + " VALUES($1, $2, $3, $4)" +
|
||||
" ON CONFLICT (path, key) DO " +
|
||||
" UPDATE SET (parent_path, path, key, value) = ($1, $2, $3, $4)"
|
||||
}
|
||||
|
||||
// Setup the backend.
|
||||
m := &PostgreSQLBackend{
|
||||
table: quoted_table,
|
||||
client: db,
|
||||
statements: make(map[string]*sql.Stmt),
|
||||
table: quoted_table,
|
||||
client: db,
|
||||
put_query: put_query,
|
||||
get_query: "SELECT value FROM " + quoted_table + " WHERE path = $1 AND key = $2",
|
||||
delete_query: "DELETE FROM " + quoted_table + " WHERE path = $1 AND key = $2",
|
||||
list_query: "SELECT key FROM " + quoted_table + " WHERE path = $1" +
|
||||
"UNION SELECT substr(path, length($1)+1) FROM " + quoted_table + "WHERE parent_path = $1",
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// Prepare all the statements required
|
||||
statements := map[string]string{
|
||||
"put": put_statement,
|
||||
"get": "SELECT value FROM " + quoted_table + " WHERE path = $1 AND key = $2",
|
||||
"delete": "DELETE FROM " + quoted_table + " WHERE path = $1 AND key = $2",
|
||||
"list": "SELECT key FROM " + quoted_table + " WHERE path = $1" +
|
||||
"UNION SELECT substr(path, length($1)+1) FROM " + quoted_table + "WHERE parent_path = $1",
|
||||
}
|
||||
for name, query := range statements {
|
||||
if err := m.prepare(name, query); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// prepare is a helper to prepare a query for future execution
|
||||
func (m *PostgreSQLBackend) prepare(name, query string) error {
|
||||
stmt, err := m.client.Prepare(query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare '%s': %v", name, err)
|
||||
}
|
||||
m.statements[name] = stmt
|
||||
return nil
|
||||
}
|
||||
|
||||
// splitKey is a helper to split a full path key into individual
|
||||
// parts: parentPath, path, key
|
||||
func (m *PostgreSQLBackend) splitKey(fullPath string) (string, string, string) {
|
||||
|
@ -123,7 +107,7 @@ func (m *PostgreSQLBackend) Put(entry *Entry) error {
|
|||
|
||||
parentPath, path, key := m.splitKey(entry.Key)
|
||||
|
||||
_, err := m.statements["put"].Exec(parentPath, path, key, entry.Value)
|
||||
_, err := m.client.Exec(m.put_query, parentPath, path, key, entry.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -137,7 +121,7 @@ func (m *PostgreSQLBackend) Get(fullPath string) (*Entry, error) {
|
|||
_, path, key := m.splitKey(fullPath)
|
||||
|
||||
var result []byte
|
||||
err := m.statements["get"].QueryRow(path, key).Scan(&result)
|
||||
err := m.client.QueryRow(m.get_query, path, key).Scan(&result)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -158,7 +142,7 @@ func (m *PostgreSQLBackend) Delete(fullPath string) error {
|
|||
|
||||
_, path, key := m.splitKey(fullPath)
|
||||
|
||||
_, err := m.statements["delete"].Exec(path, key)
|
||||
_, err := m.client.Exec(m.delete_query, path, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -170,7 +154,7 @@ func (m *PostgreSQLBackend) Delete(fullPath string) error {
|
|||
func (m *PostgreSQLBackend) List(prefix string) ([]string, error) {
|
||||
defer metrics.MeasureSince([]string{"postgres", "list"}, time.Now())
|
||||
|
||||
rows, err := m.statements["list"].Query("/" + prefix)
|
||||
rows, err := m.client.Query(m.list_query, "/" + prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestPostgreSQLBackend(t *testing.T) {
|
|||
|
||||
defer func() {
|
||||
pg := b.(*PostgreSQLBackend)
|
||||
_, err := pg.client.Exec("DROP TABLE " + pg.table)
|
||||
_, err := pg.client.Exec("TRUNCATE TABLE " + pg.table)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to drop table: %v", err)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -92,8 +91,7 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
|
|||
|
||||
t.tokenLocks = map[string]*sync.RWMutex{}
|
||||
for i := int64(0); i < 256; i++ {
|
||||
t.tokenLocks[fmt.Sprintf("%2x",
|
||||
strconv.FormatInt(i, 16))] = &sync.RWMutex{}
|
||||
t.tokenLocks[fmt.Sprintf("%02x", i)] = &sync.RWMutex{}
|
||||
}
|
||||
t.tokenLocks["custom"] = &sync.RWMutex{}
|
||||
|
||||
|
|
Loading…
Reference in a new issue