mirror of
https://github.com/hashicorp/vault.git
synced 2026-06-09 08:55:13 -04:00
Merge branch 'master-oss' into acl-parameters-permission
This commit is contained in:
commit
e2b7d43e01
29 changed files with 352 additions and 127 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -5,6 +5,16 @@ IMPROVEMENTS:
|
|||
* auth/ldap: Use the value of the `LOGNAME` or `USER` env vars for the
|
||||
username if not explicitly set on the command line when authenticating
|
||||
[GH-2154]
|
||||
* audit: Support adding a configurable prefix (such as `@cee`) before each
|
||||
line [GH-2359]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* auth/aws-ec2: Return role period in seconds and not nanoseconds [GH-2374]
|
||||
* auth/okta: Fix panic if user had no local groups and/or policies set
|
||||
[GH-2367]
|
||||
* command/server: Fix parsing of redirect address when port is not mentioned
|
||||
[GH-2354]
|
||||
|
||||
## 0.6.5 (February 7th, 2017)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,22 @@ import (
|
|||
|
||||
// JSONFormatWriter is an AuditFormatWriter implementation that structures data into
|
||||
// a JSON format.
|
||||
type JSONFormatWriter struct{}
|
||||
type JSONFormatWriter struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (f *JSONFormatWriter) WriteRequest(w io.Writer, req *AuditRequestEntry) error {
|
||||
if req == nil {
|
||||
return fmt.Errorf("request entry was nil, cannot encode")
|
||||
}
|
||||
|
||||
if len(f.Prefix) > 0 {
|
||||
_, err := w.Write([]byte(f.Prefix))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
return enc.Encode(req)
|
||||
}
|
||||
|
|
@ -24,6 +33,13 @@ func (f *JSONFormatWriter) WriteResponse(w io.Writer, resp *AuditResponseEntry)
|
|||
return fmt.Errorf("response entry was nil, cannot encode")
|
||||
}
|
||||
|
||||
if len(f.Prefix) > 0 {
|
||||
_, err := w.Write([]byte(f.Prefix))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
return enc.Encode(resp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
Auth *logical.Auth
|
||||
Req *logical.Request
|
||||
Err error
|
||||
Prefix string
|
||||
Result string
|
||||
}{
|
||||
"auth, request": {
|
||||
|
|
@ -37,6 +38,26 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
},
|
||||
},
|
||||
errors.New("this is an error"),
|
||||
"",
|
||||
testFormatJSONReqBasicStr,
|
||||
},
|
||||
"auth, request with prefix": {
|
||||
&logical.Auth{ClientToken: "foo", Policies: []string{"root"}},
|
||||
&logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "/foo",
|
||||
Connection: &logical.Connection{
|
||||
RemoteAddr: "127.0.0.1",
|
||||
},
|
||||
WrapInfo: &logical.RequestWrapInfo{
|
||||
TTL: 60 * time.Second,
|
||||
},
|
||||
Headers: map[string][]string{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
},
|
||||
errors.New("this is an error"),
|
||||
"@cee: ",
|
||||
testFormatJSONReqBasicStr,
|
||||
},
|
||||
}
|
||||
|
|
@ -44,7 +65,9 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
for name, tc := range cases {
|
||||
var buf bytes.Buffer
|
||||
formatter := AuditFormatter{
|
||||
AuditFormatWriter: &JSONFormatWriter{},
|
||||
AuditFormatWriter: &JSONFormatWriter{
|
||||
Prefix: tc.Prefix,
|
||||
},
|
||||
}
|
||||
salter, _ := salt.NewSalt(nil, nil)
|
||||
config := FormatterConfig{
|
||||
|
|
@ -54,13 +77,17 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
t.Fatalf("bad: %s\nerr: %s", name, err)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(buf.String(), tc.Prefix) {
|
||||
t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, tc.Result, tc.Prefix)
|
||||
}
|
||||
|
||||
var expectedjson = new(AuditRequestEntry)
|
||||
if err := jsonutil.DecodeJSON([]byte(tc.Result), &expectedjson); err != nil {
|
||||
t.Fatalf("bad json: %s", err)
|
||||
}
|
||||
|
||||
var actualjson = new(AuditRequestEntry)
|
||||
if err := jsonutil.DecodeJSON([]byte(buf.String()), &actualjson); err != nil {
|
||||
if err := jsonutil.DecodeJSON([]byte(buf.String())[len(tc.Prefix):], &actualjson); err != nil {
|
||||
t.Fatalf("bad json: %s", err)
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +98,7 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
t.Fatalf("unable to marshal json: %s", err)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(buf.String()) != string(expectedBytes) {
|
||||
if !strings.HasSuffix(strings.TrimSpace(buf.String()), string(expectedBytes)) {
|
||||
t.Fatalf(
|
||||
"bad: %s\nResult:\n\n'%s'\n\nExpected:\n\n'%s'",
|
||||
name, buf.String(), string(expectedBytes))
|
||||
|
|
|
|||
|
|
@ -10,13 +10,22 @@ import (
|
|||
|
||||
// JSONxFormatWriter is an AuditFormatWriter implementation that structures data into
|
||||
// a XML format.
|
||||
type JSONxFormatWriter struct{}
|
||||
type JSONxFormatWriter struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (f *JSONxFormatWriter) WriteRequest(w io.Writer, req *AuditRequestEntry) error {
|
||||
if req == nil {
|
||||
return fmt.Errorf("request entry was nil, cannot encode")
|
||||
}
|
||||
|
||||
if len(f.Prefix) > 0 {
|
||||
_, err := w.Write([]byte(f.Prefix))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -36,6 +45,13 @@ func (f *JSONxFormatWriter) WriteResponse(w io.Writer, resp *AuditResponseEntry)
|
|||
return fmt.Errorf("response entry was nil, cannot encode")
|
||||
}
|
||||
|
||||
if len(f.Prefix) > 0 {
|
||||
_, err := w.Write([]byte(f.Prefix))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
Auth *logical.Auth
|
||||
Req *logical.Request
|
||||
Err error
|
||||
Prefix string
|
||||
Result string
|
||||
Expected string
|
||||
}{
|
||||
|
|
@ -37,6 +38,27 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
},
|
||||
errors.New("this is an error"),
|
||||
"",
|
||||
"",
|
||||
`<json:object name="auth"><json:string name="accessor"></json:string><json:string name="client_token"></json:string><json:string name="display_name"></json:string><json:null name="metadata" /><json:array name="policies"><json:string>root</json:string></json:array></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token"></json:string><json:string name="client_token_accessor"></json:string><json:null name="data" /><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id"></json:string><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
},
|
||||
"auth, request with prefix": {
|
||||
&logical.Auth{ClientToken: "foo", Policies: []string{"root"}},
|
||||
&logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "/foo",
|
||||
Connection: &logical.Connection{
|
||||
RemoteAddr: "127.0.0.1",
|
||||
},
|
||||
WrapInfo: &logical.RequestWrapInfo{
|
||||
TTL: 60 * time.Second,
|
||||
},
|
||||
Headers: map[string][]string{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
},
|
||||
errors.New("this is an error"),
|
||||
"",
|
||||
"@cee: ",
|
||||
`<json:object name="auth"><json:string name="accessor"></json:string><json:string name="client_token"></json:string><json:string name="display_name"></json:string><json:null name="metadata" /><json:array name="policies"><json:string>root</json:string></json:array></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token"></json:string><json:string name="client_token_accessor"></json:string><json:null name="data" /><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id"></json:string><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
},
|
||||
}
|
||||
|
|
@ -44,7 +66,9 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
for name, tc := range cases {
|
||||
var buf bytes.Buffer
|
||||
formatter := AuditFormatter{
|
||||
AuditFormatWriter: &JSONxFormatWriter{},
|
||||
AuditFormatWriter: &JSONxFormatWriter{
|
||||
Prefix: tc.Prefix,
|
||||
},
|
||||
}
|
||||
salter, _ := salt.NewSalt(nil, nil)
|
||||
config := FormatterConfig{
|
||||
|
|
@ -55,7 +79,11 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
t.Fatalf("bad: %s\nerr: %s", name, err)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(buf.String()) != string(tc.Expected) {
|
||||
if !strings.HasPrefix(buf.String(), tc.Prefix) {
|
||||
t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, tc.Result, tc.Prefix)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(strings.TrimSpace(buf.String()), string(tc.Expected)) {
|
||||
t.Fatalf(
|
||||
"bad: %s\nResult:\n\n'%s'\n\nExpected:\n\n'%s'",
|
||||
name, strings.TrimSpace(buf.String()), string(tc.Expected))
|
||||
|
|
|
|||
|
|
@ -76,9 +76,13 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
|
|||
|
||||
switch format {
|
||||
case "json":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
case "jsonx":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the file can be successfully opened for writing;
|
||||
|
|
|
|||
|
|
@ -87,9 +87,13 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
|
|||
|
||||
switch format {
|
||||
case "json":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
case "jsonx":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
|
|
|
|||
|
|
@ -74,9 +74,13 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
|
|||
|
||||
switch format {
|
||||
case "json":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
case "jsonx":
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{}
|
||||
b.formatter.AuditFormatWriter = &audit.JSONxFormatWriter{
|
||||
Prefix: conf.Config["prefix"],
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
|
|
|
|||
|
|
@ -272,10 +272,10 @@ func (b *backend) pathRoleRead(
|
|||
// HMAC key belonging to the role should NOT be exported.
|
||||
delete(respData, "hmac_key")
|
||||
|
||||
// Display the ttl in seconds.
|
||||
// Display all the durations in seconds
|
||||
respData["ttl"] = roleEntry.TTL / time.Second
|
||||
// Display the max_ttl in seconds.
|
||||
respData["max_ttl"] = roleEntry.MaxTTL / time.Second
|
||||
respData["period"] = roleEntry.Period / time.Second
|
||||
|
||||
return &logical.Response{
|
||||
Data: respData,
|
||||
|
|
|
|||
59
builtin/credential/aws-ec2/path_role_test.go
Normal file
59
builtin/credential/aws-ec2/path_role_test.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package awsec2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
func TestAwsEc2_RoleDurationSeconds(t *testing.T) {
|
||||
config := logical.TestBackendConfig()
|
||||
storage := &logical.InmemStorage{}
|
||||
config.StorageView = storage
|
||||
|
||||
b, err := Backend(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = b.Setup(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
roleData := map[string]interface{}{
|
||||
"bound_iam_instance_profile_arn": "testarn",
|
||||
"ttl": "10s",
|
||||
"max_ttl": "20s",
|
||||
"period": "30s",
|
||||
}
|
||||
|
||||
roleReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
Storage: storage,
|
||||
Path: "role/testrole",
|
||||
Data: roleData,
|
||||
}
|
||||
|
||||
resp, err := b.HandleRequest(roleReq)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("resp: %#v, err: %v", resp, err)
|
||||
}
|
||||
|
||||
roleReq.Operation = logical.ReadOperation
|
||||
|
||||
resp, err = b.HandleRequest(roleReq)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("resp: %#v, err: %v", resp, err)
|
||||
}
|
||||
|
||||
if int64(resp.Data["ttl"].(time.Duration)) != 10 {
|
||||
t.Fatalf("bad: period; expected: 10, actual: %d", resp.Data["ttl"])
|
||||
}
|
||||
if int64(resp.Data["max_ttl"].(time.Duration)) != 20 {
|
||||
t.Fatalf("bad: period; expected: 20, actual: %d", resp.Data["max_ttl"])
|
||||
}
|
||||
if int64(resp.Data["period"].(time.Duration)) != 30 {
|
||||
t.Fatalf("bad: period; expected: 30, actual: %d", resp.Data["period"])
|
||||
}
|
||||
}
|
||||
|
|
@ -135,8 +135,7 @@ func TestBackend_basic(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepConfigUrl(t),
|
||||
// Map Scientists group (from LDAP server) with foo policy
|
||||
|
|
@ -164,8 +163,7 @@ func TestBackend_basic_authbind(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepConfigUrlWithAuthBind(t),
|
||||
testAccStepGroup(t, "Scientists", "foo"),
|
||||
|
|
@ -180,8 +178,7 @@ func TestBackend_basic_discover(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepConfigUrlWithDiscover(t),
|
||||
testAccStepGroup(t, "Scientists", "foo"),
|
||||
|
|
@ -196,8 +193,7 @@ func TestBackend_basic_nogroupdn(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepConfigUrlNoGroupDN(t),
|
||||
testAccStepGroup(t, "Scientists", "foo"),
|
||||
|
|
@ -212,8 +208,7 @@ func TestBackend_groupCrud(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepGroup(t, "g1", "foo"),
|
||||
testAccStepReadGroup(t, "g1", "default,foo"),
|
||||
|
|
@ -230,8 +225,7 @@ func TestBackend_configDefaultsAfterUpdate(t *testing.T) {
|
|||
b := factory(t)
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: false,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
|
|
@ -297,7 +291,8 @@ func testAccStepConfigUrlWithAuthBind(t *testing.T) logicaltest.TestStep {
|
|||
Data: map[string]interface{}{
|
||||
// Online LDAP test server
|
||||
// http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
|
||||
"url": "ldap://ldap.forumsys.com",
|
||||
// In this test we also exercise multiple URL support
|
||||
"url": "foobar://ldap.example.com,ldap://ldap.forumsys.com",
|
||||
"userattr": "uid",
|
||||
"userdn": "dc=example,dc=com",
|
||||
"groupdn": "dc=example,dc=com",
|
||||
|
|
@ -388,8 +383,7 @@ func TestBackend_userCrud(t *testing.T) {
|
|||
b := Backend()
|
||||
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
AcceptanceTest: true,
|
||||
Backend: b,
|
||||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepUser(t, "g1", "bar"),
|
||||
testAccStepReadUser(t, "g1", "bar"),
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ import (
|
|||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-ldap/ldap"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/vault/helper/tlsutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
log "github.com/mgutz/logxi/v1"
|
||||
)
|
||||
|
||||
func pathConfig(b *backend) *framework.Path {
|
||||
|
|
@ -23,7 +25,7 @@ func pathConfig(b *backend) *framework.Path {
|
|||
"url": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "ldap://127.0.0.1",
|
||||
Description: "ldap URL to connect to (default: ldap://127.0.0.1)",
|
||||
Description: "LDAP URL to connect to (default: ldap://127.0.0.1). Multiple URLs can be specified by concatenating them with commas; they will be tried in-order.",
|
||||
},
|
||||
|
||||
"userdn": &framework.FieldSchema{
|
||||
|
|
@ -155,6 +157,8 @@ func (b *backend) Config(req *logical.Request) (*ConfigEntry, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
result.logger = b.Logger()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
|
@ -183,6 +187,8 @@ func (b *backend) pathConfigRead(
|
|||
func (b *backend) newConfigEntry(d *framework.FieldData) (*ConfigEntry, error) {
|
||||
cfg := new(ConfigEntry)
|
||||
|
||||
cfg.logger = b.Logger()
|
||||
|
||||
url := d.Get("url").(string)
|
||||
if url != "" {
|
||||
cfg.Url = strings.ToLower(url)
|
||||
|
|
@ -294,6 +300,7 @@ func (b *backend) pathConfigWrite(
|
|||
}
|
||||
|
||||
type ConfigEntry struct {
|
||||
logger log.Logger
|
||||
Url string `json:"url" structs:"url" mapstructure:"url"`
|
||||
UserDN string `json:"userdn" structs:"userdn" mapstructure:"userdn"`
|
||||
GroupDN string `json:"groupdn" structs:"groupdn" mapstructure:"groupdn"`
|
||||
|
|
@ -348,55 +355,67 @@ func (c *ConfigEntry) GetTLSConfig(host string) (*tls.Config, error) {
|
|||
}
|
||||
|
||||
func (c *ConfigEntry) DialLDAP() (*ldap.Conn, error) {
|
||||
|
||||
u, err := url.Parse(c.Url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
host = u.Host
|
||||
}
|
||||
|
||||
var retErr *multierror.Error
|
||||
var conn *ldap.Conn
|
||||
var tlsConfig *tls.Config
|
||||
switch u.Scheme {
|
||||
case "ldap":
|
||||
if port == "" {
|
||||
port = "389"
|
||||
}
|
||||
conn, err = ldap.Dial("tcp", host+":"+port)
|
||||
urls := strings.Split(c.Url, ",")
|
||||
for _, uut := range urls {
|
||||
u, err := url.Parse(uut)
|
||||
if err != nil {
|
||||
break
|
||||
retErr = multierror.Append(retErr, fmt.Errorf("error parsing url %q: %s", uut, err.Error()))
|
||||
continue
|
||||
}
|
||||
if conn == nil {
|
||||
err = fmt.Errorf("empty connection after dialing")
|
||||
break
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
host = u.Host
|
||||
}
|
||||
if c.StartTLS {
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
switch u.Scheme {
|
||||
case "ldap":
|
||||
if port == "" {
|
||||
port = "389"
|
||||
}
|
||||
conn, err = ldap.Dial("tcp", net.JoinHostPort(host, port))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if conn == nil {
|
||||
err = fmt.Errorf("empty connection after dialing")
|
||||
break
|
||||
}
|
||||
if c.StartTLS {
|
||||
tlsConfig, err = c.GetTLSConfig(host)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = conn.StartTLS(tlsConfig)
|
||||
}
|
||||
case "ldaps":
|
||||
if port == "" {
|
||||
port = "636"
|
||||
}
|
||||
tlsConfig, err = c.GetTLSConfig(host)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = conn.StartTLS(tlsConfig)
|
||||
conn, err = ldap.DialTLS("tcp", net.JoinHostPort(host, port), tlsConfig)
|
||||
default:
|
||||
retErr = multierror.Append(retErr, fmt.Errorf("invalid LDAP scheme in url %q"))
|
||||
continue
|
||||
}
|
||||
case "ldaps":
|
||||
if port == "" {
|
||||
port = "636"
|
||||
}
|
||||
tlsConfig, err = c.GetTLSConfig(host)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
if retErr != nil {
|
||||
if c.logger.IsDebug() {
|
||||
c.logger.Debug("ldap: errors connecting to some hosts: %s", retErr.Error())
|
||||
}
|
||||
}
|
||||
retErr = nil
|
||||
break
|
||||
}
|
||||
conn, err = ldap.DialTLS("tcp", host+":"+port, tlsConfig)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid LDAP scheme")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot connect to LDAP: %v", err)
|
||||
retErr = multierror.Append(retErr, fmt.Errorf("error connecting to host %q: %s", uut, err.Error()))
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
return conn, retErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -59,10 +59,6 @@ func (b *backend) Login(req *logical.Request, username string, password string)
|
|||
return nil, logical.ErrorResponse("okta auth backend unexpected failure"), nil
|
||||
}
|
||||
|
||||
if b.Logger().IsDebug() {
|
||||
b.Logger().Debug("auth/okta:", auth)
|
||||
}
|
||||
|
||||
oktaGroups, err := b.getOktaGroups(cfg, auth.Embedded.User.ID)
|
||||
if err != nil {
|
||||
return nil, logical.ErrorResponse(err.Error()), nil
|
||||
|
|
@ -96,13 +92,15 @@ func (b *backend) Login(req *logical.Request, username string, password string)
|
|||
var policies []string
|
||||
for _, groupName := range allGroups {
|
||||
group, err := b.Group(req.Storage, groupName)
|
||||
if err == nil && group != nil {
|
||||
if err == nil && group != nil && group.Policies != nil {
|
||||
policies = append(policies, group.Policies...)
|
||||
}
|
||||
}
|
||||
|
||||
// Merge local Policies into Okta Policies
|
||||
policies = append(policies, user.Policies...)
|
||||
if user != nil && user.Policies != nil {
|
||||
policies = append(policies, user.Policies...)
|
||||
}
|
||||
|
||||
if len(policies) == 0 {
|
||||
errStr := "user is not a member of any authorized policy"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/helper/logformat"
|
||||
"github.com/hashicorp/vault/helper/policyutil"
|
||||
log "github.com/mgutz/logxi/v1"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
|
|
@ -40,23 +41,23 @@ func TestBackend_Config(t *testing.T) {
|
|||
Backend: b,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testConfigCreate(t, configData),
|
||||
testLoginWrite(t, username, "wrong", "E0000004", 0),
|
||||
testLoginWrite(t, username, password, "user is not a member of any authorized policy", 0),
|
||||
testLoginWrite(t, username, "wrong", "E0000004", nil),
|
||||
testLoginWrite(t, username, password, "user is not a member of any authorized policy", nil),
|
||||
testAccUserGroups(t, username, "local_group,local_group2"),
|
||||
testAccGroups(t, "local_group", "local_group_policy"),
|
||||
testLoginWrite(t, username, password, "", 2),
|
||||
testLoginWrite(t, username, password, "", []string{"local_group_policy"}),
|
||||
testAccGroups(t, "Everyone", "everyone_group_policy,every_group_policy2"),
|
||||
testLoginWrite(t, username, password, "", 2),
|
||||
testLoginWrite(t, username, password, "", []string{"local_group_policy"}),
|
||||
testConfigUpdate(t, configDataToken),
|
||||
testConfigRead(t, configData),
|
||||
testLoginWrite(t, username, password, "", 4),
|
||||
testAccGroups(t, "TestGroup", "testgroup_group_policy"),
|
||||
testLoginWrite(t, username, password, "", 5),
|
||||
testLoginWrite(t, username, password, "", []string{"everyone_group_policy", "every_group_policy2", "local_group_policy"}),
|
||||
testAccGroups(t, "local_group2", "testgroup_group_policy"),
|
||||
testLoginWrite(t, username, password, "", []string{"everyone_group_policy", "every_group_policy2", "local_group_policy", "testgroup_group_policy"}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testLoginWrite(t *testing.T, username, password, reason string, policies int) logicaltest.TestStep {
|
||||
func testLoginWrite(t *testing.T, username, password, reason string, policies []string) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "login/" + username,
|
||||
|
|
@ -72,8 +73,8 @@ func testLoginWrite(t *testing.T, username, password, reason string, policies in
|
|||
}
|
||||
|
||||
if resp.Auth != nil {
|
||||
if len(resp.Auth.Policies) != policies {
|
||||
return fmt.Errorf("policy mismatch expected %d but got %s", policies, resp.Auth.Policies)
|
||||
if !policyutil.EquivalentPolicies(resp.Auth.Policies, policies) {
|
||||
return fmt.Errorf("policy mismatch expected %v but got %v", policies, resp.Auth.Policies)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,15 +312,19 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
nPort, nPortErr := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
// assume it's due to there not being a port specified, in which case
|
||||
// use 443
|
||||
host = u.Host
|
||||
nPort = 443
|
||||
// This sucks, as it's a const in the function but not exported in the package
|
||||
if strings.Contains(err.Error(), "missing port in address") {
|
||||
host = u.Host
|
||||
port = "443"
|
||||
} else {
|
||||
c.Ui.Output(fmt.Sprintf("Error parsing redirect address: %v", err))
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if nPortErr != nil {
|
||||
c.Ui.Output(fmt.Sprintf("Cannot parse %s as a numeric port: %v", port, nPortErr))
|
||||
nPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
c.Ui.Output(fmt.Sprintf("Error parsing redirect address; failed to convert %q to a numeric: %v", port, err))
|
||||
return 1
|
||||
}
|
||||
u.Host = net.JoinHostPort(host, strconv.Itoa(nPort+1))
|
||||
|
|
|
|||
|
|
@ -2,11 +2,15 @@ package vault
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
// N.B.: While we could use textproto to get the canonical mime header, HTTP/2
|
||||
// requires all headers to be converted to lower case, so we just do that.
|
||||
|
||||
const (
|
||||
// Key used in the BarrierView to store and retrieve the header config
|
||||
auditedHeadersEntry = "audited-headers"
|
||||
|
|
@ -37,7 +41,7 @@ func (a *AuditedHeadersConfig) add(header string, hmac bool) error {
|
|||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.Headers[header] = &auditedHeaderSettings{hmac}
|
||||
a.Headers[strings.ToLower(header)] = &auditedHeaderSettings{hmac}
|
||||
entry, err := logical.StorageEntryJSON(auditedHeadersEntry, a.Headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist audited headers config: %v", err)
|
||||
|
|
@ -60,7 +64,7 @@ func (a *AuditedHeadersConfig) remove(header string) error {
|
|||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
delete(a.Headers, header)
|
||||
delete(a.Headers, strings.ToLower(header))
|
||||
entry, err := logical.StorageEntryJSON(auditedHeadersEntry, a.Headers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to persist audited headers config: %v", err)
|
||||
|
|
@ -80,9 +84,16 @@ func (a *AuditedHeadersConfig) ApplyConfig(headers map[string][]string, hashFunc
|
|||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
// Make a copy of the incoming headers with everything lower so we can
|
||||
// case-insensitively compare
|
||||
lowerHeaders := make(map[string][]string, len(headers))
|
||||
for k, v := range headers {
|
||||
lowerHeaders[strings.ToLower(k)] = v
|
||||
}
|
||||
|
||||
result = make(map[string][]string, len(a.Headers))
|
||||
for key, settings := range a.Headers {
|
||||
if val, ok := headers[key]; ok {
|
||||
if val, ok := lowerHeaders[key]; ok {
|
||||
// copy the header values so we don't overwrite them
|
||||
hVals := make([]string, len(val))
|
||||
copy(hVals, val)
|
||||
|
|
@ -120,8 +131,15 @@ func (c *Core) setupAuditedHeadersConfig() error {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure that we are able to case-sensitively access the headers;
|
||||
// necessary for the upgrade case
|
||||
lowerHeaders := make(map[string]*auditedHeaderSettings, len(headers))
|
||||
for k, v := range headers {
|
||||
lowerHeaders[strings.ToLower(k)] = v
|
||||
}
|
||||
|
||||
c.auditedHeaders = &AuditedHeadersConfig{
|
||||
Headers: headers,
|
||||
Headers: lowerHeaders,
|
||||
view: view,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func testAuditedHeadersConfig_Add(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
t.Fatalf("Error when adding header to config: %s", err)
|
||||
}
|
||||
|
||||
settings, ok := conf.Headers["X-Test-Header"]
|
||||
settings, ok := conf.Headers["x-test-header"]
|
||||
if !ok {
|
||||
t.Fatal("Expected header to be found in config")
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ func testAuditedHeadersConfig_Add(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
}
|
||||
|
||||
expected := map[string]*auditedHeaderSettings{
|
||||
"X-Test-Header": &auditedHeaderSettings{
|
||||
"x-test-header": &auditedHeaderSettings{
|
||||
HMAC: false,
|
||||
},
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ func testAuditedHeadersConfig_Add(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
t.Fatalf("Error when adding header to config: %s", err)
|
||||
}
|
||||
|
||||
settings, ok = conf.Headers["X-Vault-Header"]
|
||||
settings, ok = conf.Headers["x-vault-header"]
|
||||
if !ok {
|
||||
t.Fatal("Expected header to be found in config")
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ func testAuditedHeadersConfig_Add(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
t.Fatalf("Error decoding header view: %s", err)
|
||||
}
|
||||
|
||||
expected["X-Vault-Header"] = &auditedHeaderSettings{
|
||||
expected["x-vault-header"] = &auditedHeaderSettings{
|
||||
HMAC: true,
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ func testAuditedHeadersConfig_Remove(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
t.Fatalf("Error when adding header to config: %s", err)
|
||||
}
|
||||
|
||||
_, ok := conf.Headers["X-Test-Header"]
|
||||
_, ok := conf.Headers["x-Test-HeAder"]
|
||||
if ok {
|
||||
t.Fatal("Expected header to not be found in config")
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ func testAuditedHeadersConfig_Remove(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
}
|
||||
|
||||
expected := map[string]*auditedHeaderSettings{
|
||||
"X-Vault-Header": &auditedHeaderSettings{
|
||||
"x-vault-header": &auditedHeaderSettings{
|
||||
HMAC: true,
|
||||
},
|
||||
}
|
||||
|
|
@ -126,12 +126,12 @@ func testAuditedHeadersConfig_Remove(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
t.Fatalf("Expected config didn't match actual. Expected: %#v, Got: %#v", expected, headers)
|
||||
}
|
||||
|
||||
err = conf.remove("X-Vault-Header")
|
||||
err = conf.remove("x-VaulT-Header")
|
||||
if err != nil {
|
||||
t.Fatalf("Error when adding header to config: %s", err)
|
||||
}
|
||||
|
||||
_, ok = conf.Headers["X-Vault-Header"]
|
||||
_, ok = conf.Headers["x-vault-header"]
|
||||
if ok {
|
||||
t.Fatal("Expected header to not be found in config")
|
||||
}
|
||||
|
|
@ -157,10 +157,8 @@ func testAuditedHeadersConfig_Remove(t *testing.T, conf *AuditedHeadersConfig) {
|
|||
func TestAuditedHeadersConfig_ApplyConfig(t *testing.T) {
|
||||
conf := mockAuditedHeadersConfig(t)
|
||||
|
||||
conf.Headers = map[string]*auditedHeaderSettings{
|
||||
"X-Test-Header": &auditedHeaderSettings{false},
|
||||
"X-Vault-Header": &auditedHeaderSettings{true},
|
||||
}
|
||||
conf.add("X-TesT-Header", false)
|
||||
conf.add("X-Vault-HeAdEr", true)
|
||||
|
||||
reqHeaders := map[string][]string{
|
||||
"X-Test-Header": []string{"foo"},
|
||||
|
|
@ -173,8 +171,8 @@ func TestAuditedHeadersConfig_ApplyConfig(t *testing.T) {
|
|||
result := conf.ApplyConfig(reqHeaders, hashFunc)
|
||||
|
||||
expected := map[string][]string{
|
||||
"X-Test-Header": []string{"foo"},
|
||||
"X-Vault-Header": []string{"hashed", "hashed"},
|
||||
"x-test-header": []string{"foo"},
|
||||
"x-vault-header": []string{"hashed", "hashed"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(result, expected) {
|
||||
|
|
|
|||
13
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
13
vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package cleanhttp
|
|||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -22,13 +23,15 @@ func DefaultTransport() *http.Transport {
|
|||
func DefaultPooledTransport() *http.Transport {
|
||||
transport := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DisableKeepAlives: false,
|
||||
MaxIdleConnsPerHost: 1,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
|
||||
}
|
||||
return transport
|
||||
}
|
||||
|
|
|
|||
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
|
@ -601,10 +601,10 @@
|
|||
"revisionTime": "2014-10-28T05:47:10Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Uzyon2091lmwacNsl1hCytjhHtg=",
|
||||
"checksumSHA1": "6ihdHMkDfFx/rJ1A36com2F6bQk=",
|
||||
"path": "github.com/hashicorp/go-cleanhttp",
|
||||
"revision": "ad28ea4487f05916463e2423a55166280e8254b5",
|
||||
"revisionTime": "2016-04-07T17:41:26Z"
|
||||
"revision": "a45970658e51fea2c41445ff0f7e07106d007617",
|
||||
"revisionTime": "2017-02-11T00:33:01Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TNlVzNR1OaajcNi3CbQ3bGbaLGU=",
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ if [ -z "$NO_UPLOAD" ]; then
|
|||
--no-mime-magic \
|
||||
--acl-public \
|
||||
--recursive \
|
||||
--add-header="Cache-Control: max-age=31536000" \
|
||||
--add-header="Cache-Control: max-age=14400" \
|
||||
--add-header="x-amz-meta-surrogate-key: site-$PROJECT" \
|
||||
sync "$DIR/build/" "s3://hc-sites/$PROJECT/latest/"
|
||||
|
||||
|
|
@ -67,6 +67,7 @@ if [ -z "$NO_UPLOAD" ]; then
|
|||
echo "Overriding javascript mime-types..."
|
||||
s3cmd \
|
||||
--mime-type="application/javascript" \
|
||||
--add-header="Cache-Control: max-age=31536000" \
|
||||
--exclude "*" \
|
||||
--include "*.js" \
|
||||
--recursive \
|
||||
|
|
@ -75,6 +76,7 @@ if [ -z "$NO_UPLOAD" ]; then
|
|||
echo "Overriding css mime-types..."
|
||||
s3cmd \
|
||||
--mime-type="text/css" \
|
||||
--add-header="Cache-Control: max-age=31536000" \
|
||||
--exclude "*" \
|
||||
--include "*.css" \
|
||||
--recursive \
|
||||
|
|
@ -83,11 +85,11 @@ if [ -z "$NO_UPLOAD" ]; then
|
|||
echo "Overriding svg mime-types..."
|
||||
s3cmd \
|
||||
--mime-type="image/svg+xml" \
|
||||
--add-header="Cache-Control: max-age=31536000" \
|
||||
--exclude "*" \
|
||||
--include "*.svg" \
|
||||
--recursive \
|
||||
modify "s3://hc-sites/$PROJECT/latest/"
|
||||
|
||||
fi
|
||||
|
||||
# Perform a soft-purge of the surrogate key.
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ Following are the configuration options available for the backend.
|
|||
Allows selecting the output format. Valid values are `json` (the
|
||||
default) and `jsonx`, which formats the normal log entries as XML.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">prefix</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Allows a customizable string prefix to write before the actual log
|
||||
line. Defaults to an empty string.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ Following are the configuration options available for the backend.
|
|||
<span class="param-flags">optional</span>
|
||||
Sets the timeout for writes to the socket. Defaults to "2s" (2 seconds).
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">prefix</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Allows a customizable string prefix to write before the actual log
|
||||
line. Defaults to an empty string.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ Following are the configuration options available for the backend.
|
|||
Allows selecting the output format. Valid values are `json` (the
|
||||
default) and `jsonx`, which formats the normal log entries as XML.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">prefix</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Allows a customizable string prefix to write before the actual log
|
||||
line. Defaults to an empty string.
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ familiar with instance metadata, details can be found
|
|||
|
||||
One piece of "dynamic metadata" available to the EC2 instance, is the instance
|
||||
identity document, a JSON representation of a collection of instance metadata.
|
||||
Importantly, AWS also provides a copy of this metadata in PKCS#7 format signed
|
||||
with its public key, and publishes the public keys used (which are grouped by
|
||||
region). (Details on the instance identity document and the signature can be
|
||||
AWS also provides PKCS#7 signature of the instance metadata document, and
|
||||
publishes the public keys (grouped by region) which can be used to verify the
|
||||
signature. Details on the instance identity document and the signature can be
|
||||
found
|
||||
[here](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html).)
|
||||
[here](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html).
|
||||
|
||||
During login, the backend verifies the signature on the PKCS#7 document,
|
||||
ensuring that the information contained within, is certified accurate by AWS.
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ Configuration is written to `auth/ldap/config`.
|
|||
|
||||
### Connection parameters
|
||||
|
||||
* `url` (string, required) - The LDAP server to connect to. Examples: `ldap://ldap.myorg.com`, `ldaps://ldap.myorg.com:636`
|
||||
* `url` (string, required) - The LDAP server to connect to. Examples: `ldap://ldap.myorg.com`, `ldaps://ldap.myorg.com:636`. This can also be a comma-delineated list of URLs, e.g. `ldap://ldap.myorg.com,ldaps://ldap.myorg.com:636`, in which case the servers will be tried in-order if there are errors during the connection process.
|
||||
* `starttls` (bool, optional) - If true, issues a `StartTLS` command after establishing an unencrypted connection.
|
||||
* `insecure_tls` - (bool, optional) - If true, skips LDAP server SSL certificate verification - insecure, use with caution!
|
||||
* `certificate` - (string, optional) - CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded.
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ sending a SIGHUP to the server process. These are denoted below.
|
|||
subsystem. This will very significantly impact performance.
|
||||
|
||||
* `disable_mlock` (optional) - A boolean. If true, this will disable the
|
||||
server from executing the `mlock` syscall to prevent memory from being
|
||||
swapped to disk. This is not recommended in production (see below).
|
||||
server from executing the `mlock` syscall. `mlock` prevents memory from being
|
||||
swapped to disk. Disabling `mlock` is not recommended in production (see below).
|
||||
|
||||
* `telemetry` (optional) - Configures the telemetry reporting system
|
||||
(see below).
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ These libraries are provided by the community.
|
|||
|
||||
* [vault-php-sdk](https://github.com/jippi/vault-php-sdk)
|
||||
* `composer require jippi/vault-php-sdk`
|
||||
* [vault-php-sdk](https://github.com/violuke/vault-php-sdk) extended from jipppi
|
||||
* `composer require violuke/vault-php-sdk`
|
||||
|
||||
### Python
|
||||
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ only encrypt or decrypt using the named keys they need access to.
|
|||
Defaults to 0.
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">allow_deletion</span>
|
||||
<span class="param">deletion_allowed</span>
|
||||
<span class="param-flags">optional</span>
|
||||
When set, the key is allowed to be deleted. Defaults to false.
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ remains mounted.
|
|||
|
||||
```
|
||||
$ vault unmount generic/
|
||||
Successfully unmounted 'generic/'!
|
||||
Successfully unmounted 'generic/' if it was mounted
|
||||
```
|
||||
|
||||
In addition to unmounting, you can remount a backend. Remounting a
|
||||
|
|
|
|||
Loading…
Reference in a new issue