Skip to content

Commit

Permalink
Merge remote-tracking branch 'oss/master' into type-string-slice
Browse files Browse the repository at this point in the history
* oss/master: (43 commits)
  Bump deps
  Update SSH docs to indicate deprecation of dynamic key type
  Bump Go version in Travis
  changelog++
  Bump go version to 1.8.1
  Consider new bounds as a criteria to allow role creation (#2600)
  Update 404.html.md (#2594)
  Add some extra documentation around ssh-keygen -L to see signed cert info.
  changelog++
  Respect the configured address's path in the client (#2588)
  changelog++
  Verify that a CSR specifies IP SANs before checking whether it's allowed (#2574)
  minor docs update
  changelog++
  Update AES-GCM verification text
  changelog++
  implement a no_store option for pki roles (#2565)
  Remove superfluous/misleading comments around some listener options
  Update SSH CA documentation
  Add press-kit
  ...
  • Loading branch information
Chris Hoffman committed Apr 17, 2017
2 parents d5d930d + cccfb2d commit 35300a7
Show file tree
Hide file tree
Showing 610 changed files with 76,380 additions and 7,144 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
- docker

go:
- 1.8
- 1.8.1

matrix:
allow_failures:
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
## 0.7.1 (Unreleased)

FEATURES:

* **MSSQL Physical Backend**: You can now use Microsoft SQL Server as your
Vault physical data store [GH-2546]

IMPROVEMENTS:

* secret/pki: Add `no_store` option that allows certificates to be issued
without being stored. This removes the ability to look up and/or add to a
CRL but helps with scaling to very large numbers of certificates. [GH-2565]
* storage/s3: Support `max_parallel` option to limit concurrent outstanding
requests [GH-2466]
* storage/s3: Use pooled transport for http client [GH-2481]
* storage/etcd3: Add `discovery_srv` option to query for SRV records to find
servers [GH-2521]

BUG FIXES:

* api: Respect a configured path in Vault's address [GH-2588]
* auth/aws-ec2: New bounds added as criteria to allow role creation [GH-2600]
* secret/pki: Don't lowercase O/OU values in certs [GH-2555]
* secret/pki: Don't attempt to validate IP SANs if none are provided [GH-2574]
* storage/consul: Properly handle state events rather than timing out
[GH-2548]
* storage/etcd3: Ensure locks are released if client is improperly shut down
[GH-2526]

Expand Down
15 changes: 8 additions & 7 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"sync"
"time"
"path"

"golang.org/x/net/http2"

Expand Down Expand Up @@ -329,27 +330,27 @@ func (c *Client) ClearToken() {
// NewRequest creates a new raw request object to query the Vault server
// configured for this client. This is an advanced method and generally
// doesn't need to be called externally.
func (c *Client) NewRequest(method, path string) *Request {
func (c *Client) NewRequest(method, requestPath string) *Request {
req := &Request{
Method: method,
URL: &url.URL{
User: c.addr.User,
Scheme: c.addr.Scheme,
Host: c.addr.Host,
Path: path,
Path: path.Join(c.addr.Path, requestPath),
},
ClientToken: c.token,
Params: make(map[string][]string),
}

var lookupPath string
switch {
case strings.HasPrefix(path, "/v1/"):
lookupPath = strings.TrimPrefix(path, "/v1/")
case strings.HasPrefix(path, "v1/"):
lookupPath = strings.TrimPrefix(path, "v1/")
case strings.HasPrefix(requestPath, "/v1/"):
lookupPath = strings.TrimPrefix(requestPath, "/v1/")
case strings.HasPrefix(requestPath, "v1/"):
lookupPath = strings.TrimPrefix(requestPath, "v1/")
default:
lookupPath = path
lookupPath = requestPath
}
if c.wrappingLookupFunc != nil {
req.WrapTTL = c.wrappingLookupFunc(method, lookupPath)
Expand Down
2 changes: 1 addition & 1 deletion builtin/credential/approle/path_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -2086,7 +2086,7 @@ or the 'role/<role_name>/custom-secret-id' endpoints, and if those SecretIDs
are used to perform the login operation, then the value of 'token-max-ttl'
defines the maximum lifetime of the tokens issued, after which the tokens
cannot be renewed. A reauthentication is required after this duration.
This value will be croleed by the backend mount's maximum TTL value.`,
This value will be capped by the backend mount's maximum TTL value.`,
},
"role-id": {
"Returns the 'role_id' of the role.",
Expand Down
2 changes: 1 addition & 1 deletion builtin/credential/approle/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type secretIDStorageEntry struct {
// operation
SecretIDNumUses int `json:"secret_id_num_uses" structs:"secret_id_num_uses" mapstructure:"secret_id_num_uses"`

// Duration after which this SecretID should expire. This is croleed by
// Duration after which this SecretID should expire. This is capped by
// the backend mount's max TTL value.
SecretIDTTL time.Duration `json:"secret_id_ttl" structs:"secret_id_ttl" mapstructure:"secret_id_ttl"`

Expand Down
8 changes: 5 additions & 3 deletions builtin/credential/aws-ec2/path_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,14 @@ func (b *backend) pathRoleCreateUpdate(

// Ensure that at least one bound is set on the role
switch {
case roleEntry.BoundAccountID != "":
case roleEntry.BoundAmiID != "":
case roleEntry.BoundIamInstanceProfileARN != "":
case roleEntry.BoundAccountID != "":
case roleEntry.BoundRegion != "":
case roleEntry.BoundVpcID != "":
case roleEntry.BoundSubnetID != "":
case roleEntry.BoundIamRoleARN != "":
case roleEntry.BoundIamInstanceProfileARN != "":
default:

return logical.ErrorResponse("at least be one bound parameter should be specified on the role"), nil
}

Expand Down
30 changes: 22 additions & 8 deletions builtin/credential/aws-ec2/path_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
)

func TestAwsEc2_RoleCrud(t *testing.T) {
var err error
var resp *logical.Response
config := logical.TestBackendConfig()
storage := &logical.InmemStorage{}
config.StorageView = storage
Expand All @@ -22,6 +24,23 @@ func TestAwsEc2_RoleCrud(t *testing.T) {
t.Fatal(err)
}

role1Data := map[string]interface{}{
"bound_vpc_id": "testvpcid",
"allow_instance_migration": true,
"policies": "testpolicy1,testpolicy2",
}
roleReq := &logical.Request{
Operation: logical.UpdateOperation,
Storage: storage,
Path: "role/role1",
Data: role1Data,
}

resp, err = b.HandleRequest(roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("resp: %#v, err: %v", resp, err)
}

roleData := map[string]interface{}{
"bound_ami_id": "testamiid",
"bound_account_id": "testaccountid",
Expand All @@ -40,14 +59,9 @@ func TestAwsEc2_RoleCrud(t *testing.T) {
"period": "1m",
}

roleReq := &logical.Request{
Operation: logical.UpdateOperation,
Storage: storage,
Path: "role/testrole",
Data: roleData,
}

resp, err := b.HandleRequest(roleReq)
roleReq.Path = "role/testrole"
roleReq.Data = roleData
resp, err = b.HandleRequest(roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("resp: %#v, err: %v", resp, err)
}
Expand Down
4 changes: 2 additions & 2 deletions builtin/credential/ldap/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,11 @@ func (b *backend) Login(req *logical.Request, username string, password string)
policies = append(policies, group.Policies...)
}
}
if user !=nil && user.Policies != nil {
if user != nil && user.Policies != nil {
policies = append(policies, user.Policies...)
}
// Policies from each group may overlap
policies = strutil.RemoveDuplicates(policies)
policies = strutil.RemoveDuplicates(policies, true)

if len(policies) == 0 {
errStr := "user is not a member of any authorized group"
Expand Down
8 changes: 7 additions & 1 deletion builtin/logical/pki/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func TestBackend_RSARoles_CSR(t *testing.T) {

stepCount = len(testCase.Steps)

testCase.Steps = append(testCase.Steps, generateRoleSteps(t, false)...)
testCase.Steps = append(testCase.Steps, generateRoleSteps(t, true)...)
if len(os.Getenv("VAULT_VERBOSE_PKITESTS")) > 0 {
for i, v := range testCase.Steps {
fmt.Printf("Step %d:\n%+v\n\n", i+stepCount, v)
Expand Down Expand Up @@ -1787,6 +1787,12 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
}
// IP SAN tests
{
roleVals.UseCSRSANs = true
roleVals.AllowIPSANs = false
issueTestStep.ErrorOk = false
addTests(nil)

roleVals.UseCSRSANs = false
issueVals.IPSANs = "127.0.0.1,::1"
issueTestStep.ErrorOk = true
addTests(nil)
Expand Down
14 changes: 8 additions & 6 deletions builtin/logical/pki/cert_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,11 +634,13 @@ func generateCreationBundle(b *backend,
var ipAltInt interface{}
{
if csr != nil && role.UseCSRSANs {
if !role.AllowIPSANs {
return nil, errutil.UserError{Err: fmt.Sprintf(
"IP Subject Alternative Names are not allowed in this role, but was provided some via CSR")}
if len(csr.IPAddresses) > 0 {
if !role.AllowIPSANs {
return nil, errutil.UserError{Err: fmt.Sprintf(
"IP Subject Alternative Names are not allowed in this role, but was provided some via CSR")}
}
ipAddresses = csr.IPAddresses
}
ipAddresses = csr.IPAddresses
} else {
ipAltInt, ok = data.GetOk("ip_sans")
if ok {
Expand All @@ -665,15 +667,15 @@ func generateCreationBundle(b *backend,
ou := []string{}
{
if role.OU != "" {
ou = strutil.ParseDedupAndSortStrings(role.OU, ",")
ou = strutil.RemoveDuplicates(strutil.ParseStringSlice(role.OU, ","), false)
}
}

// Set O (organization) values if specified in the role
organization := []string{}
{
if role.Organization != "" {
organization = strutil.ParseDedupAndSortStrings(role.Organization, ",")
organization = strutil.RemoveDuplicates(strutil.ParseStringSlice(role.Organization, ","), false)
}
}

Expand Down
14 changes: 8 additions & 6 deletions builtin/logical/pki/path_issue_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,14 @@ func (b *backend) pathIssueSignCert(
resp.Secret.TTL = parsedBundle.Certificate.NotAfter.Sub(time.Now())
}

err = req.Storage.Put(&logical.StorageEntry{
Key: "certs/" + cb.SerialNumber,
Value: parsedBundle.CertificateBytes,
})
if err != nil {
return nil, fmt.Errorf("Unable to store certificate locally: %v", err)
if !role.NoStore {
err = req.Storage.Put(&logical.StorageEntry{
Key: "certs/" + cb.SerialNumber,
Value: parsedBundle.CertificateBytes,
})
if err != nil {
return nil, fmt.Errorf("Unable to store certificate locally: %v", err)
}
}

return resp, nil
Expand Down
20 changes: 19 additions & 1 deletion builtin/logical/pki/path_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,17 @@ to the CRL. When large number of certificates are generated with long
lifetimes, it is recommended that lease generation be disabled, as large amount of
leases adversely affect the startup time of Vault.`,
},
"no_store": &framework.FieldSchema{
Type: framework.TypeBool,
Default: false,
Description: `
If set, certificates issued/signed against this role will not be stored in the
in the storage backend. This can improve performance when issuing large numbers
of certificates. However, certificates issued in this way cannot be enumerated
or revoked, so this option is recommended only for certificates that are
non-sensitive, or extremely short-lived. This option implies a value of "false"
for "generate_lease".`,
},
},

Callbacks: map[logical.Operation]framework.OperationFunc{
Expand Down Expand Up @@ -384,9 +395,15 @@ func (b *backend) pathRoleCreate(
OU: data.Get("ou").(string),
Organization: data.Get("organization").(string),
GenerateLease: new(bool),
NoStore: data.Get("no_store").(bool),
}

*entry.GenerateLease = data.Get("generate_lease").(bool)
// no_store implies generate_lease := false
if entry.NoStore {
*entry.GenerateLease = false
} else {
*entry.GenerateLease = data.Get("generate_lease").(bool)
}

if entry.KeyType == "rsa" && entry.KeyBits < 2048 {
return logical.ErrorResponse("RSA keys < 2048 bits are unsafe and not supported"), nil
Expand Down Expand Up @@ -504,6 +521,7 @@ type roleEntry struct {
OU string `json:"ou" structs:"ou" mapstructure:"ou"`
Organization string `json:"organization" structs:"organization" mapstructure:"organization"`
GenerateLease *bool `json:"generate_lease,omitempty" structs:"generate_lease,omitempty"`
NoStore bool `json:"no_store" structs:"no_store" mapstructure:"no_store"`
}

const pathListRolesHelpSyn = `List the existing roles in this backend`
Expand Down
Loading

0 comments on commit 35300a7

Please sign in to comment.