From efadfb5775f9837075fe7c9f30ca1688a0f65757 Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Sun, 28 Apr 2019 16:24:23 -0400
Subject: [PATCH 01/12] Initial porting

---
 audit/format.go                               |   4 +
 audit/format_json_test.go                     |  24 +-
 audit/format_jsonx_test.go                    |  26 +-
 sdk/go.sum                                    |   1 +
 sdk/helper/tokenhelper/tokenhelper.go         | 206 +++++++++++
 sdk/logical/auth.go                           |   5 +
 sdk/plugin/pb/backend.pb.go                   | 324 +++++++++---------
 sdk/plugin/pb/backend.proto                   |   3 +
 sdk/plugin/pb/translation.go                  |   2 +
 .../external_tests/policy/no_default_test.go  |  85 +++++
 vault/request_handling.go                     |   7 +-
 11 files changed, 506 insertions(+), 181 deletions(-)
 create mode 100644 sdk/helper/tokenhelper/tokenhelper.go
 create mode 100644 vault/external_tests/policy/no_default_test.go

diff --git a/audit/format.go b/audit/format.go
index 7cbf771a70a9..f0baaaf9ad3c 100644
--- a/audit/format.go
+++ b/audit/format.go
@@ -132,6 +132,7 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config
 			TokenPolicies:             auth.TokenPolicies,
 			IdentityPolicies:          auth.IdentityPolicies,
 			ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
+			NoDefaultPolicy:           auth.NoDefaultPolicy,
 			Metadata:                  auth.Metadata,
 			EntityID:                  auth.EntityID,
 			RemainingUses:             req.ClientTokenRemainingUses,
@@ -304,6 +305,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
 			TokenPolicies:             resp.Auth.TokenPolicies,
 			IdentityPolicies:          resp.Auth.IdentityPolicies,
 			ExternalNamespacePolicies: resp.Auth.ExternalNamespacePolicies,
+			NoDefaultPolicy:           resp.Auth.NoDefaultPolicy,
 			Metadata:                  resp.Auth.Metadata,
 			NumUses:                   resp.Auth.NumUses,
 			EntityID:                  resp.Auth.EntityID,
@@ -345,6 +347,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
 			TokenPolicies:             auth.TokenPolicies,
 			IdentityPolicies:          auth.IdentityPolicies,
 			ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
+			NoDefaultPolicy:           auth.NoDefaultPolicy,
 			Metadata:                  auth.Metadata,
 			RemainingUses:             req.ClientTokenRemainingUses,
 			EntityID:                  auth.EntityID,
@@ -442,6 +445,7 @@ type AuditAuth struct {
 	TokenPolicies             []string            `json:"token_policies,omitempty"`
 	IdentityPolicies          []string            `json:"identity_policies,omitempty"`
 	ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies,omitempty"`
+	NoDefaultPolicy           bool                `json:"no_default_policy,omitempty"`
 	Metadata                  map[string]string   `json:"metadata"`
 	NumUses                   int                 `json:"num_uses,omitempty"`
 	RemainingUses             int                 `json:"remaining_uses,omitempty"`
diff --git a/audit/format_json_test.go b/audit/format_json_test.go
index f11934bf53df..7fa1bed2a76c 100644
--- a/audit/format_json_test.go
+++ b/audit/format_json_test.go
@@ -38,11 +38,12 @@ func TestFormatJSON_formatRequest(t *testing.T) {
 	}{
 		"auth, request": {
 			&logical.Auth{
-				ClientToken: "foo",
-				Accessor:    "bar",
-				DisplayName: "testtoken",
-				Policies:    []string{"root"},
-				TokenType:   logical.TokenTypeService,
+				ClientToken:     "foo",
+				Accessor:        "bar",
+				DisplayName:     "testtoken",
+				NoDefaultPolicy: true,
+				Policies:        []string{"root"},
+				TokenType:       logical.TokenTypeService,
 			},
 			&logical.Request{
 				Operation: logical.UpdateOperation,
@@ -63,11 +64,12 @@ func TestFormatJSON_formatRequest(t *testing.T) {
 		},
 		"auth, request with prefix": {
 			&logical.Auth{
-				ClientToken: "foo",
-				Accessor:    "bar",
-				DisplayName: "testtoken",
-				Policies:    []string{"root"},
-				TokenType:   logical.TokenTypeService,
+				ClientToken:     "foo",
+				Accessor:        "bar",
+				DisplayName:     "testtoken",
+				NoDefaultPolicy: true,
+				Policies:        []string{"root"},
+				TokenType:       logical.TokenTypeService,
 			},
 			&logical.Request{
 				Operation: logical.UpdateOperation,
@@ -139,5 +141,5 @@ func TestFormatJSON_formatRequest(t *testing.T) {
 	}
 }
 
-const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"metadata":null,"entity_id":"","token_type":"service"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"}
+const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"no_default_policy":true,"metadata":null,"entity_id":"","token_type":"service"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"}
 `
diff --git a/audit/format_jsonx_test.go b/audit/format_jsonx_test.go
index ce4b85a7c7b6..f7c8cdb4dde2 100644
--- a/audit/format_jsonx_test.go
+++ b/audit/format_jsonx_test.go
@@ -37,11 +37,12 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
 	}{
 		"auth, request": {
 			&logical.Auth{
-				ClientToken: "foo",
-				Accessor:    "bar",
-				DisplayName: "testtoken",
-				Policies:    []string{"root"},
-				TokenType:   logical.TokenTypeService,
+				ClientToken:     "foo",
+				Accessor:        "bar",
+				DisplayName:     "testtoken",
+				NoDefaultPolicy: true,
+				Policies:        []string{"root"},
+				TokenType:       logical.TokenTypeService,
 			},
 			&logical.Request{
 				Operation: logical.UpdateOperation,
@@ -59,16 +60,17 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
 			errors.New("this is an error"),
 			"",
 			"",
-			fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id"></json:string><json:null name="metadata" /><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></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:object name="namespace"><json:string name="id">root</json:string><json:string name="path"></json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">false</json:boolean><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>`,
+			fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id"></json:string><json:null name="metadata" /><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></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:object name="namespace"><json:string name="id">root</json:string><json:string name="path"></json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">false</json:boolean><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>`,
 				fooSalted),
 		},
 		"auth, request with prefix": {
 			&logical.Auth{
-				ClientToken: "foo",
-				Accessor:    "bar",
-				DisplayName: "testtoken",
-				Policies:    []string{"root"},
-				TokenType:   logical.TokenTypeService,
+				ClientToken:     "foo",
+				Accessor:        "bar",
+				DisplayName:     "testtoken",
+				NoDefaultPolicy: true,
+				Policies:        []string{"root"},
+				TokenType:       logical.TokenTypeService,
 			},
 			&logical.Request{
 				Operation: logical.UpdateOperation,
@@ -86,7 +88,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
 			errors.New("this is an error"),
 			"",
 			"@cee: ",
-			fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id"></json:string><json:null name="metadata" /><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></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:object name="namespace"><json:string name="id">root</json:string><json:string name="path"></json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">false</json:boolean><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>`,
+			fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id"></json:string><json:null name="metadata" /><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></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:object name="namespace"><json:string name="id">root</json:string><json:string name="path"></json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">false</json:boolean><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>`,
 				fooSalted),
 		},
 	}
diff --git a/sdk/go.sum b/sdk/go.sum
index 2238d1fea1ac..5be807c7e084 100644
--- a/sdk/go.sum
+++ b/sdk/go.sum
@@ -52,6 +52,7 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/vault v1.1.2 h1:NDaWEwrTwjg3VKrKQmQykuiq4UqMUlbqloRvIX5fhns=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
diff --git a/sdk/helper/tokenhelper/tokenhelper.go b/sdk/helper/tokenhelper/tokenhelper.go
new file mode 100644
index 000000000000..f5624fc9a190
--- /dev/null
+++ b/sdk/helper/tokenhelper/tokenhelper.go
@@ -0,0 +1,206 @@
+package tokenhelper
+
+import (
+	"errors"
+	"fmt"
+	"time"
+
+	sockaddr "github.com/hashicorp/go-sockaddr"
+	"github.com/hashicorp/vault/sdk/framework"
+	"github.com/hashicorp/vault/sdk/helper/parseutil"
+	"github.com/hashicorp/vault/sdk/helper/strutil"
+	"github.com/hashicorp/vault/sdk/logical"
+)
+
+type TokenParams struct {
+	// The set of CIDRs that tokens generated using this role will be bound to
+	TokenBoundCIDRs []*sockaddr.SockAddrMarshaler `json:"token_bound_cidrs"`
+
+	// If set, the token entry will have an explicit maximum TTL set, rather
+	// than deferring to role/mount values
+	TokenExplicitMaxTTL time.Duration `json:"token_explicit_max_ttl" mapstructure:"token_explicit_max_ttl"`
+
+	// The max TTL to use for the token
+	TokenMaxTTL time.Duration `json:"token_max_ttl" mapstructure:"token_max_ttl"`
+
+	// If set, core will not automatically add default to the policy list
+	TokenNoDefaultPolicy bool `json:"token_no_default_policy" mapstructure:"token_no_default_policy"`
+
+	// If non-zero, tokens created using this role will be able to be renewed
+	// forever, but will have a fixed renewal period of this value
+	TokenPeriod time.Duration `json:"token_period" mapstructure:"token_period"`
+
+	// The policies to set
+	TokenPolicies []string `json:"token_policies" mapstructure:"token_policies"`
+
+	// The type of token this role should issue
+	TokenType logical.TokenType `json:"token_type" mapstructure:"token_type"`
+
+	// The TTL to user for the token
+	TokenTTL time.Duration `json:"token_ttl" mapstructure:"token_ttl"`
+}
+
+// AddTokenFields adds fields to an existing role. It panics if it would
+// overwrite an existing field.
+func AddTokenFields(m map[string]*framework.FieldSchema) {
+	AddTokenFieldsWithAllowList(m, nil)
+}
+
+func AddTokenFieldsWithAllowList(m map[string]*framework.FieldSchema, allowed []string) {
+	r := TokenFields()
+	for k, v := range r {
+		if len(allowed) > 0 && !strutil.StrListContains(allowed, k) {
+			continue
+		}
+		if _, has := m[k]; has {
+			panic(fmt.Sprintf("adding role field %s would overwrite existing field", k))
+		}
+		m[k] = v
+	}
+}
+
+func TokenFields() map[string]*framework.FieldSchema {
+	return map[string]*framework.FieldSchema{
+		"token_bound_cidrs": &framework.FieldSchema{
+			Type:        framework.TypeCommaStringSlice,
+			Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`,
+		},
+
+		"token_explicit_max_ttl": &framework.FieldSchema{
+			Type:        framework.TypeDurationSecond,
+			Description: tokenExplicitMaxTTLHelp,
+		},
+
+		"token_max_ttl": &framework.FieldSchema{
+			Type:        framework.TypeDurationSecond,
+			Description: "The maximum lifetime of the generated token",
+		},
+
+		"token_no_default_policy": &framework.FieldSchema{
+			Type:        framework.TypeBool,
+			Description: "If true, the 'default' policy will not automatically be added to generated tokens",
+		},
+
+		"token_period": &framework.FieldSchema{
+			Type:        framework.TypeDurationSecond,
+			Description: tokenPeriodHelp,
+		},
+
+		"token_policies": &framework.FieldSchema{
+			Type:        framework.TypeCommaStringSlice,
+			Description: "Comma-separated list of policies",
+		},
+
+		"token_type": &framework.FieldSchema{
+			Type:        framework.TypeString,
+			Description: "The type of token to generate, service or batch",
+		},
+
+		"token_ttl": &framework.FieldSchema{
+			Type:        framework.TypeDurationSecond,
+			Description: "The initial ttl of the token to generate",
+		},
+	}
+}
+
+func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldData) error {
+	if boundCIDRsRaw, ok := d.GetOk("token_bound_cidrs"); ok {
+		boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
+		if err != nil {
+			return err
+		}
+		t.TokenBoundCIDRs = boundCIDRs
+	}
+
+	if explicitMaxTTLRaw, ok := d.GetOk("token_explicit_max_ttl"); ok {
+		t.TokenExplicitMaxTTL = time.Duration(explicitMaxTTLRaw.(int)) * time.Second
+	}
+
+	if maxTTLRaw, ok := d.GetOk("token_max_ttl"); ok {
+		t.TokenMaxTTL = time.Duration(maxTTLRaw.(int)) * time.Second
+	}
+	if t.TokenMaxTTL < 0 {
+		return errors.New("'token_max_ttl' cannot be negative")
+	}
+
+	if noDefaultRaw, ok := d.GetOk("token_no_default_policy"); ok {
+		t.TokenNoDefaultPolicy = noDefaultRaw.(bool)
+	}
+
+	if periodRaw, ok := d.GetOk("token_period"); ok {
+		t.TokenPeriod = time.Duration(periodRaw.(int)) * time.Second
+	}
+	if t.TokenPeriod < 0 {
+		return errors.New("'token_period' cannot be negative")
+	}
+
+	if policiesRaw, ok := d.GetOk("token_policies"); ok {
+		t.TokenPolicies = policiesRaw.([]string)
+	}
+
+	if tokenTypeRaw, ok := d.GetOk("token_type"); ok {
+		var tokenType logical.TokenType
+		tokenTypeStr := tokenTypeRaw.(string)
+		switch tokenTypeStr {
+		case "service":
+			tokenType = logical.TokenTypeService
+		case "batch":
+			tokenType = logical.TokenTypeBatch
+		case "default-service":
+			tokenType = logical.TokenTypeDefaultService
+		case "default-batch":
+			tokenType = logical.TokenTypeDefaultBatch
+		default:
+			return fmt.Errorf("invalid 'token_type' value %q", tokenTypeStr)
+		}
+		t.TokenType = tokenType
+	}
+
+	if ttlRaw, ok := d.GetOk("token_ttl"); ok {
+		t.TokenTTL = time.Duration(ttlRaw.(int)) * time.Second
+	}
+	if t.TokenTTL < 0 {
+		return errors.New("'token_ttl' cannot be negative")
+	}
+	if t.TokenTTL > 0 && t.TokenMaxTTL > 0 && t.TokenTTL > t.TokenMaxTTL {
+		return errors.New("'token_ttl' cannot be greater than 'token_max_ttl'")
+	}
+
+	return nil
+}
+
+func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
+	m["token_bound_cidrs"] = t.TokenBoundCIDRs
+	m["token_explicit_max_ttl"] = t.TokenExplicitMaxTTL.Seconds()
+	m["token_max_ttl"] = t.TokenMaxTTL.Seconds()
+	m["token_no_default_policy"] = t.TokenNoDefaultPolicy
+	m["token_period"] = t.TokenPeriod.Seconds()
+	m["token_policies"] = t.TokenPolicies
+	m["token_type"] = t.TokenType.String()
+	m["token_ttl"] = t.TokenTTL.Seconds()
+}
+
+func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
+	auth.BoundCIDRs = t.TokenBoundCIDRs
+	auth.ExplicitMaxTTL = t.TokenExplicitMaxTTL
+	auth.MaxTTL = t.TokenMaxTTL
+	auth.NoDefaultPolicy = t.TokenNoDefaultPolicy
+	auth.Period = t.TokenPeriod
+	auth.Policies = t.TokenPolicies
+	auth.TokenType = t.TokenType
+	auth.TTL = t.TokenTTL
+}
+
+const (
+	tokenPeriodHelp = `If set, tokens created via this role
+will have no max lifetime; instead, their
+renewal period will be fixed to this value.
+This takes an integer number of seconds,
+or a string duration (e.g. "24h").`
+	tokenExplicitMaxTTLHelp = `If set, tokens created via this role
+carry an explicit maximum TTL. During renewal,
+the current maximum TTL values of the role
+and the mount are not checked for changes,
+and any updates to these values will have
+no effect on the token being renewed.`
+)
diff --git a/sdk/logical/auth.go b/sdk/logical/auth.go
index 89aa9165909a..2bfb6e0015a1 100644
--- a/sdk/logical/auth.go
+++ b/sdk/logical/auth.go
@@ -38,6 +38,11 @@ type Auth struct {
 	// different namespaces indexed by respective namespace identifiers
 	ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies" mapstructure:"external_namespace_policies" structs:"external_namespace_policies"`
 
+	// Indicates that the default policy should not be added by core when
+	// creating a token. The default policy will still be added if it's
+	// explicitly defined.
+	NoDefaultPolicy bool `json:"no_default_policy" mapstructure:"no_default_policy" structs:"no_default_policy"`
+
 	// Metadata is used to attach arbitrary string-type metadata to
 	// an authenticated user. This metadata will be outputted into the
 	// audit log.
diff --git a/sdk/plugin/pb/backend.pb.go b/sdk/plugin/pb/backend.pb.go
index f2ab2b6b865f..bfa10aaf699e 100644
--- a/sdk/plugin/pb/backend.pb.go
+++ b/sdk/plugin/pb/backend.pb.go
@@ -528,7 +528,9 @@ type Auth struct {
 	// TTL is a hard limit and cannot be exceeded, also counts for periodic tokens.
 	ExplicitMaxTTL int64 `sentinel:"" protobuf:"varint,16,opt,name=explicit_max_ttl,json=explicitMaxTtl,proto3" json:"explicit_max_ttl,omitempty"`
 	// TokenType is the type of token being requested
-	TokenType            uint32   `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
+	TokenType uint32 `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
+	// Whether the default policy should be added automatically by core
+	NoDefaultPolicy      bool     `sentinel:"" protobuf:"varint,18,opt,name=no_default_policy,json=noDefaultPolicy,proto3" json:"no_default_policy,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -678,6 +680,13 @@ func (m *Auth) GetTokenType() uint32 {
 	return 0
 }
 
+func (m *Auth) GetNoDefaultPolicy() bool {
+	if m != nil {
+		return m.NoDefaultPolicy
+	}
+	return false
+}
+
 type TokenEntry struct {
 	ID                   string            `sentinel:"" protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
 	Accessor             string            `sentinel:"" protobuf:"bytes,2,opt,name=accessor,proto3" json:"accessor,omitempty"`
@@ -2715,164 +2724,165 @@ func init() {
 func init() { proto.RegisterFile("sdk/plugin/pb/backend.proto", fileDescriptor_4dbf1dfe0c11846b) }
 
 var fileDescriptor_4dbf1dfe0c11846b = []byte{
-	// 2499 bytes of a gzipped FileDescriptorProto
+	// 2519 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0xdb, 0x72, 0x1b, 0xc7,
 	0xd1, 0x2e, 0x00, 0xc4, 0xa9, 0x71, 0x22, 0x46, 0xb4, 0xfe, 0x15, 0x24, 0xff, 0x82, 0xd7, 0x91,
-	0x0c, 0x2b, 0x36, 0x68, 0x51, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
-	0x6b, 0x09, 0xc5, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
-	0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xa6, 0x72, 0x93, 0xbb, 0x94, 0x2b, 0xf7, 0x79, 0x8d,
-	0x3c, 0x43, 0x6a, 0x7a, 0x66, 0x4f, 0x00, 0x68, 0xc9, 0x55, 0xce, 0xdd, 0x4c, 0x77, 0xcf, 0xa9,
-	0xe7, 0xeb, 0xaf, 0x7b, 0x76, 0xe1, 0x6e, 0xe4, 0x5c, 0xee, 0x86, 0x5e, 0x3c, 0x77, 0xfd, 0xdd,
-	0x70, 0xb6, 0x3b, 0xa3, 0xf6, 0x25, 0xf3, 0x9d, 0x71, 0xc8, 0x03, 0x11, 0x90, 0x72, 0x38, 0x1b,
-	0xdc, 0x9f, 0x07, 0xc1, 0xdc, 0x63, 0xbb, 0x28, 0x99, 0xc5, 0xe7, 0xbb, 0xc2, 0x5d, 0xb0, 0x48,
-	0xd0, 0x45, 0xa8, 0x8c, 0x06, 0x03, 0x39, 0x83, 0x17, 0xcc, 0x5d, 0x9b, 0x7a, 0xbb, 0xae, 0xc3,
-	0x7c, 0xe1, 0x8a, 0xa5, 0xd6, 0x19, 0x79, 0x9d, 0x5a, 0x45, 0x69, 0xcc, 0x3a, 0x54, 0x0f, 0x17,
-	0xa1, 0x58, 0x9a, 0x43, 0xa8, 0x7d, 0xc1, 0xa8, 0xc3, 0x38, 0xb9, 0x0d, 0xb5, 0x0b, 0x6c, 0x19,
-	0xa5, 0x61, 0x65, 0xd4, 0xb4, 0x74, 0xcf, 0xfc, 0x03, 0xc0, 0xa9, 0x1c, 0x73, 0xc8, 0x79, 0xc0,
-	0xc9, 0x1d, 0x68, 0x30, 0xce, 0xa7, 0x62, 0x19, 0x32, 0xa3, 0x34, 0x2c, 0x8d, 0x3a, 0x56, 0x9d,
-	0x71, 0x3e, 0x59, 0x86, 0x8c, 0xfc, 0x1f, 0xc8, 0xe6, 0x74, 0x11, 0xcd, 0x8d, 0xf2, 0xb0, 0x24,
-	0x67, 0x60, 0x9c, 0x9f, 0x44, 0xf3, 0x64, 0x8c, 0x1d, 0x38, 0xcc, 0xa8, 0x0c, 0x4b, 0xa3, 0x0a,
-	0x8e, 0x39, 0x08, 0x1c, 0x66, 0xfe, 0xa5, 0x04, 0xd5, 0x53, 0x2a, 0x2e, 0x22, 0x42, 0x60, 0x8b,
-	0x07, 0x81, 0xd0, 0x8b, 0x63, 0x9b, 0x8c, 0xa0, 0x17, 0xfb, 0x34, 0x16, 0x17, 0xf2, 0x54, 0x36,
-	0x15, 0xcc, 0x31, 0xca, 0xa8, 0x5e, 0x15, 0x93, 0xb7, 0xa1, 0xe3, 0x05, 0x36, 0xf5, 0xa6, 0x91,
-	0x08, 0x38, 0x9d, 0xcb, 0x75, 0xa4, 0x5d, 0x1b, 0x85, 0x67, 0x4a, 0x46, 0x1e, 0x41, 0x3f, 0x62,
-	0xd4, 0x9b, 0xbe, 0xe4, 0x34, 0x4c, 0x0d, 0xb7, 0xd4, 0x84, 0x52, 0xf1, 0x0d, 0xa7, 0xa1, 0xb6,
-	0x35, 0xff, 0x51, 0x83, 0xba, 0xc5, 0xfe, 0x14, 0xb3, 0x48, 0x90, 0x2e, 0x94, 0x5d, 0x07, 0x4f,
-	0xdb, 0xb4, 0xca, 0xae, 0x43, 0xc6, 0x40, 0x2c, 0x16, 0x7a, 0x72, 0x69, 0x37, 0xf0, 0x0f, 0xbc,
-	0x38, 0x12, 0x8c, 0xeb, 0x33, 0x6f, 0xd0, 0x90, 0x7b, 0xd0, 0x0c, 0x42, 0xc6, 0x51, 0x86, 0x0e,
-	0x68, 0x5a, 0x99, 0x40, 0x1e, 0x3c, 0xa4, 0xe2, 0xc2, 0xd8, 0x42, 0x05, 0xb6, 0xa5, 0xcc, 0xa1,
-	0x82, 0x1a, 0x55, 0x25, 0x93, 0x6d, 0x62, 0x42, 0x2d, 0x62, 0x36, 0x67, 0xc2, 0xa8, 0x0d, 0x4b,
-	0xa3, 0xd6, 0x1e, 0x8c, 0xc3, 0xd9, 0xf8, 0x0c, 0x25, 0x96, 0xd6, 0x90, 0x7b, 0xb0, 0x25, 0xfd,
-	0x62, 0xd4, 0xd1, 0xa2, 0x21, 0x2d, 0xf6, 0x63, 0x71, 0x61, 0xa1, 0x94, 0xec, 0x41, 0x5d, 0xdd,
-	0x69, 0x64, 0x34, 0x86, 0x95, 0x51, 0x6b, 0xcf, 0x90, 0x06, 0xfa, 0x94, 0x63, 0x05, 0x83, 0xe8,
-	0xd0, 0x17, 0x7c, 0x69, 0x25, 0x86, 0xe4, 0x2d, 0x68, 0xdb, 0x9e, 0xcb, 0x7c, 0x31, 0x15, 0xc1,
-	0x25, 0xf3, 0x8d, 0x26, 0xee, 0xa8, 0xa5, 0x64, 0x13, 0x29, 0x22, 0x7b, 0xf0, 0x46, 0xde, 0x64,
-	0x4a, 0x6d, 0x9b, 0x45, 0x51, 0xc0, 0x0d, 0x40, 0xdb, 0x5b, 0x39, 0xdb, 0x7d, 0xad, 0x92, 0xd3,
-	0x3a, 0x6e, 0x14, 0x7a, 0x74, 0x39, 0xf5, 0xe9, 0x82, 0x19, 0x2d, 0x35, 0xad, 0x96, 0x7d, 0x45,
-	0x17, 0x8c, 0xdc, 0x87, 0xd6, 0x22, 0x88, 0x7d, 0x31, 0x0d, 0x03, 0xd7, 0x17, 0x46, 0x1b, 0x2d,
-	0x00, 0x45, 0xa7, 0x52, 0x42, 0xde, 0x04, 0xd5, 0x53, 0x60, 0xec, 0x28, 0xbf, 0xa2, 0x04, 0xe1,
-	0xf8, 0x00, 0xba, 0x4a, 0x9d, 0xee, 0xa7, 0x8b, 0x26, 0x1d, 0x94, 0xa6, 0x3b, 0xf9, 0x00, 0x9a,
-	0x88, 0x07, 0xd7, 0x3f, 0x0f, 0x8c, 0x1e, 0xfa, 0xed, 0x56, 0xce, 0x2d, 0x12, 0x13, 0x47, 0xfe,
-	0x79, 0x60, 0x35, 0x5e, 0xea, 0x16, 0xf9, 0x04, 0xee, 0x16, 0xce, 0xcb, 0xd9, 0x82, 0xba, 0xbe,
-	0xeb, 0xcf, 0xa7, 0x71, 0xc4, 0x22, 0x63, 0x1b, 0x11, 0x6e, 0xe4, 0x4e, 0x6d, 0x25, 0x06, 0x2f,
-	0x22, 0x16, 0x91, 0xbb, 0xd0, 0x54, 0x41, 0x3a, 0x75, 0x1d, 0xa3, 0x8f, 0x5b, 0x6a, 0x28, 0xc1,
-	0x91, 0x43, 0xde, 0x81, 0x5e, 0x18, 0x78, 0xae, 0xbd, 0x9c, 0x06, 0x57, 0x8c, 0x73, 0xd7, 0x61,
-	0x06, 0x19, 0x96, 0x46, 0x0d, 0xab, 0xab, 0xc4, 0x5f, 0x6b, 0xe9, 0xa6, 0xd0, 0xb8, 0x85, 0x86,
-	0x6b, 0xa1, 0x31, 0x06, 0xb0, 0x03, 0xdf, 0x67, 0x36, 0xc2, 0x6f, 0x07, 0x4f, 0xd8, 0x95, 0x27,
-	0x3c, 0x48, 0xa5, 0x56, 0xce, 0x62, 0xf0, 0x39, 0xb4, 0xf3, 0x50, 0x20, 0xdb, 0x50, 0xb9, 0x64,
-	0x4b, 0x0d, 0x7f, 0xd9, 0x24, 0x43, 0xa8, 0x5e, 0x51, 0x2f, 0x66, 0x08, 0x79, 0x0d, 0x44, 0x35,
-	0xc4, 0x52, 0x8a, 0x5f, 0x94, 0x9f, 0x96, 0xcc, 0xbf, 0x57, 0x61, 0x4b, 0x82, 0x8f, 0x7c, 0x08,
-	0x1d, 0x8f, 0xd1, 0x88, 0x4d, 0x83, 0x50, 0x2e, 0x10, 0xe1, 0x54, 0xad, 0xbd, 0x6d, 0x39, 0xec,
-	0x58, 0x2a, 0xbe, 0x56, 0x72, 0xab, 0xed, 0xe5, 0x7a, 0x32, 0xa4, 0x5d, 0x5f, 0x30, 0xee, 0x53,
-	0x6f, 0x8a, 0xc1, 0xa0, 0x02, 0xac, 0x9d, 0x08, 0x9f, 0xc9, 0xa0, 0x58, 0xc5, 0x51, 0x65, 0x1d,
-	0x47, 0x03, 0x68, 0xa0, 0xef, 0x5c, 0x16, 0xe9, 0x60, 0x4f, 0xfb, 0x64, 0x0f, 0x1a, 0x0b, 0x26,
-	0xa8, 0x8e, 0x35, 0x19, 0x12, 0xb7, 0x93, 0x98, 0x19, 0x9f, 0x68, 0x85, 0x0a, 0x88, 0xd4, 0x6e,
-	0x2d, 0x22, 0x6a, 0xeb, 0x11, 0x31, 0x80, 0x46, 0x0a, 0xba, 0xba, 0xba, 0xe1, 0xa4, 0x2f, 0x69,
-	0x36, 0x64, 0xdc, 0x0d, 0x1c, 0xa3, 0x81, 0x40, 0xd1, 0x3d, 0x49, 0x92, 0x7e, 0xbc, 0x50, 0x10,
-	0x6a, 0x2a, 0x92, 0xf4, 0xe3, 0xc5, 0x3a, 0x62, 0x60, 0x05, 0x31, 0x3f, 0x81, 0x2a, 0xf5, 0x5c,
-	0x1a, 0x61, 0x08, 0xc9, 0x9b, 0xd5, 0x7c, 0x3f, 0xde, 0x97, 0x52, 0x4b, 0x29, 0xc9, 0x13, 0xe8,
-	0xcc, 0x79, 0x10, 0x87, 0x53, 0xec, 0xb2, 0xc8, 0x68, 0xe3, 0x69, 0x57, 0xad, 0xdb, 0x68, 0xb4,
-	0xaf, 0x6c, 0x64, 0x04, 0xce, 0x82, 0xd8, 0x77, 0xa6, 0xb6, 0xeb, 0xf0, 0xc8, 0xe8, 0xa0, 0xf3,
-	0x00, 0x45, 0x07, 0x52, 0x22, 0x43, 0x4c, 0x85, 0x40, 0xea, 0xe0, 0x2e, 0xda, 0x74, 0x50, 0x7a,
-	0x9a, 0x78, 0xf9, 0xa7, 0xd0, 0x4f, 0x12, 0x53, 0x66, 0xd9, 0x43, 0xcb, 0xed, 0x44, 0x91, 0x1a,
-	0x8f, 0x60, 0x9b, 0x5d, 0x4b, 0x0a, 0x75, 0xc5, 0x74, 0x41, 0xaf, 0xa7, 0x42, 0x78, 0x3a, 0xa4,
-	0xba, 0x89, 0xfc, 0x84, 0x5e, 0x4f, 0x84, 0x27, 0xe3, 0x5f, 0xad, 0x8e, 0xf1, 0xdf, 0xc7, 0x64,
-	0xd4, 0x44, 0x89, 0x8c, 0xff, 0xc1, 0x2f, 0xa1, 0x53, 0xb8, 0xc2, 0x0d, 0x40, 0xde, 0xc9, 0x03,
-	0xb9, 0x99, 0x07, 0xef, 0xbf, 0xb6, 0x00, 0xf0, 0x2e, 0xd5, 0xd0, 0xd5, 0x0c, 0x90, 0xbf, 0xe0,
-	0xf2, 0x86, 0x0b, 0xa6, 0x9c, 0xf9, 0x42, 0x83, 0x51, 0xf7, 0xbe, 0x17, 0x87, 0x49, 0x0e, 0xa8,
-	0xe6, 0x72, 0xc0, 0x7b, 0xb0, 0x25, 0x31, 0x67, 0xd4, 0x32, 0xaa, 0xce, 0x76, 0x84, 0xe8, 0x54,
-	0xc8, 0x44, 0xab, 0xb5, 0x40, 0xa8, 0xaf, 0x07, 0x42, 0x1e, 0x61, 0x8d, 0x22, 0xc2, 0xde, 0x86,
-	0x8e, 0xcd, 0x19, 0xe6, 0xa3, 0xa9, 0x2c, 0x30, 0x34, 0x02, 0xdb, 0x89, 0x70, 0xe2, 0x2e, 0x98,
-	0xf4, 0x9f, 0xbc, 0x0c, 0x40, 0x95, 0x6c, 0x6e, 0xbc, 0xab, 0xd6, 0xc6, 0xbb, 0xc2, 0xec, 0xee,
-	0x31, 0xcd, 0xe2, 0xd8, 0xce, 0x45, 0x42, 0xa7, 0x10, 0x09, 0x05, 0xb8, 0x77, 0x57, 0xe0, 0xbe,
-	0x82, 0xc9, 0xde, 0x1a, 0x26, 0xdf, 0x82, 0xb6, 0x74, 0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6,
-	0x95, 0x23, 0x52, 0xd9, 0x91, 0x83, 0x11, 0x1c, 0xcf, 0x66, 0xcb, 0x8b, 0xc0, 0x63, 0x19, 0x09,
-	0xb7, 0x52, 0xd9, 0x91, 0x23, 0xf7, 0x8b, 0xa8, 0x22, 0x88, 0x2a, 0x6c, 0x0f, 0x3e, 0x82, 0x66,
-	0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d, 0x27, 0x3a, 0x39, 0x78, 0x32, 0x39, 0xc6,
-	0xc1, 0x15, 0x4b, 0x36, 0x65, 0x89, 0xc0, 0x99, 0xcf, 0x5e, 0xd2, 0x99, 0xa7, 0x26, 0x68, 0x58,
-	0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0, 0xaa, 0x62, 0x65, 0x02, 0xf2, 0x31, 0x80,
-	0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x34, 0x30, 0x18, 0xab, 0xba, 0x71, 0x9c, 0xd4, 0x8d,
-	0xe3, 0x49, 0x52, 0x37, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b, 0xbd, 0x0d, 0x35, 0x79, 0x41, 0x93, 0x63,
-	0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53, 0x95, 0xc5, 0xff, 0x94, 0xbc, 0xef, 0x40,
-	0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f, 0x72, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58,
-	0x14, 0x06, 0x7e, 0xc4, 0x72, 0x95, 0x4f, 0xe9, 0x95, 0x95, 0x4f, 0x79, 0x63, 0xe5, 0x93, 0xd4,
-	0x53, 0x95, 0x5c, 0x3d, 0x35, 0x80, 0x06, 0x67, 0x8e, 0xcb, 0x99, 0x2d, 0x74, 0xed, 0x95, 0xf6,
-	0xa5, 0xee, 0x25, 0xe5, 0x32, 0x65, 0x47, 0x98, 0x17, 0x9a, 0x56, 0xda, 0x27, 0x8f, 0xf3, 0x05,
-	0x83, 0x2a, 0xc5, 0x76, 0x54, 0xc1, 0xa0, 0xb6, 0xbb, 0xa1, 0x62, 0x78, 0x92, 0x15, 0x5e, 0x75,
-	0x8c, 0xe6, 0x3b, 0xf9, 0x01, 0x9b, 0x2b, 0xaf, 0x1f, 0x2d, 0x0f, 0x7f, 0x57, 0x86, 0xed, 0xd5,
-	0xbd, 0x6d, 0x40, 0xe0, 0x0e, 0x54, 0x55, 0x3e, 0xd3, 0xf0, 0x15, 0x6b, 0x99, 0xac, 0xb2, 0x42,
-	0x74, 0xbf, 0x5a, 0x25, 0x8d, 0x57, 0x43, 0xaf, 0x48, 0x28, 0xef, 0xc2, 0xb6, 0x74, 0x51, 0xc8,
-	0x9c, 0xac, 0x46, 0x53, 0x0c, 0xd8, 0xd3, 0xf2, 0xb4, 0x4a, 0x7b, 0x04, 0xfd, 0xc4, 0x34, 0xe3,
-	0x86, 0x5a, 0xc1, 0xf6, 0x30, 0xa1, 0x88, 0xdb, 0x50, 0x3b, 0x0f, 0xf8, 0x82, 0x0a, 0x4d, 0x82,
-	0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64, 0x22, 0x94, 0xef, 0x10, 0x49, 0x3e, 0xe9,
-	0x1b, 0x01, 0x59, 0xb0, 0x61, 0x35, 0x92, 0xb7, 0x81, 0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x85, 0x1b,
-	0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9, 0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x05,
-	0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0xf7, 0xf9, 0x3c, 0x92, 0x09, 0x4e, 0xbf, 0x52, 0xa6, 0x3a, 0xfb,
-	0x74, 0xac, 0xa6, 0x96, 0x1c, 0x39, 0xe4, 0x01, 0xd4, 0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0xea,
-	0x56, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d, 0x1f, 0x28, 0x4b, 0x32, 0x92, 0xe8, 0x57,
-	0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5, 0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02,
-	0x0b, 0xc7, 0xec, 0x39, 0x68, 0x49, 0x95, 0xf9, 0x33, 0xe8, 0x9f, 0x85, 0xcc, 0x76, 0xa9, 0x87,
-	0x4f, 0x39, 0xb5, 0xc0, 0x7d, 0xa8, 0x4a, 0x27, 0x27, 0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72,
-	0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x0e, 0xaf, 0xdd, 0x48, 0x30, 0xdf, 0x66, 0x07, 0x17, 0xcc, 0xbe,
-	0xfc, 0x11, 0x4f, 0x7e, 0x05, 0x77, 0x36, 0xad, 0x90, 0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x5c,
-	0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x97, 0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34,
-	0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xcd, 0xfe, 0xf8, 0x5b, 0x09, 0x9a, 0x67, 0x4c, 0xc4, 0x21,
-	0x9e, 0xe5, 0x2e, 0x34, 0x67, 0x3c, 0xb8, 0x64, 0x3c, 0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1c, 0xf2,
-	0x18, 0x6a, 0x07, 0x81, 0x7f, 0xee, 0xce, 0xf1, 0x61, 0xab, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a,
-	0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x13, 0xbc, 0x78, 0x71, 0xf4, 0x2c, 0xa9, 0x78,
-	0x73, 0xa2, 0xc1, 0xc7, 0xd0, 0xca, 0x0d, 0xfc, 0x41, 0xa9, 0xea, 0xff, 0x01, 0x70, 0x75, 0xe5,
-	0xa3, 0x6d, 0x75, 0x54, 0x3d, 0x52, 0x1e, 0xed, 0x3e, 0x34, 0x65, 0x71, 0xa5, 0xd4, 0x49, 0x92,
-	0x2c, 0x65, 0x49, 0xd2, 0x7c, 0x00, 0xfd, 0x23, 0xff, 0x8a, 0x7a, 0xae, 0x43, 0x05, 0xfb, 0x92,
-	0x2d, 0xd1, 0x05, 0x6b, 0x3b, 0x30, 0xcf, 0xa0, 0xad, 0x5f, 0xda, 0xaf, 0xb5, 0xc7, 0xb6, 0xde,
-	0xe3, 0xf7, 0x07, 0xd1, 0xbb, 0xd0, 0xd3, 0x93, 0x1e, 0xbb, 0x3a, 0x84, 0x64, 0x8d, 0xc1, 0xd9,
-	0xb9, 0x7b, 0xad, 0xa7, 0xd6, 0x3d, 0xf3, 0x29, 0x6c, 0xe7, 0x4c, 0xd3, 0xe3, 0x5c, 0xb2, 0x65,
-	0x94, 0x7c, 0x81, 0x90, 0xed, 0xc4, 0x03, 0xe5, 0xcc, 0x03, 0x26, 0x74, 0xf5, 0xc8, 0xe7, 0x4c,
-	0xdc, 0x70, 0xba, 0x2f, 0xd3, 0x8d, 0x3c, 0x67, 0x7a, 0xf2, 0x87, 0x50, 0x65, 0xf2, 0xa4, 0xf9,
-	0xfc, 0x99, 0xf7, 0x80, 0xa5, 0xd4, 0x1b, 0x16, 0x7c, 0x9a, 0x2e, 0x78, 0x1a, 0xab, 0x05, 0x5f,
-	0x73, 0x2e, 0xf3, 0xed, 0x74, 0x1b, 0xa7, 0xb1, 0xb8, 0xe9, 0x46, 0x1f, 0x40, 0x5f, 0x1b, 0x3d,
-	0x63, 0x1e, 0x13, 0xec, 0x86, 0x23, 0x3d, 0x04, 0x52, 0x30, 0xbb, 0x69, 0xba, 0x7b, 0xd0, 0x98,
-	0x4c, 0x8e, 0x53, 0x6d, 0x91, 0x1b, 0xcd, 0x4f, 0xa0, 0x7f, 0x16, 0x3b, 0xc1, 0x29, 0x77, 0xaf,
-	0x5c, 0x8f, 0xcd, 0xd5, 0x62, 0x49, 0xf1, 0x5b, 0xca, 0x15, 0xbf, 0x1b, 0xb3, 0x91, 0x39, 0x02,
-	0x52, 0x18, 0x9e, 0xde, 0x5b, 0x14, 0x3b, 0x81, 0x0e, 0x61, 0x6c, 0x9b, 0x23, 0x68, 0x4f, 0xa8,
-	0x2c, 0x36, 0x1c, 0x65, 0x63, 0x40, 0x5d, 0xa8, 0xbe, 0x36, 0x4b, 0xba, 0xe6, 0x1e, 0xec, 0x1c,
-	0x50, 0xfb, 0xc2, 0xf5, 0xe7, 0xcf, 0xdc, 0x48, 0x56, 0x5b, 0x7a, 0xc4, 0x00, 0x1a, 0x8e, 0x16,
-	0xe8, 0x21, 0x69, 0xdf, 0x7c, 0x1f, 0xde, 0xc8, 0x7d, 0xe6, 0x39, 0x13, 0x34, 0xf1, 0xc7, 0x0e,
-	0x54, 0x23, 0xd9, 0xc3, 0x11, 0x55, 0x4b, 0x75, 0xcc, 0xaf, 0x60, 0x27, 0x9f, 0x80, 0x65, 0xed,
-	0x93, 0x1c, 0x1c, 0xab, 0x92, 0x52, 0xae, 0x2a, 0xd1, 0x3e, 0x2b, 0x67, 0xf9, 0x64, 0x1b, 0x2a,
-	0xbf, 0xfe, 0x66, 0xa2, 0xc1, 0x2e, 0x9b, 0xe6, 0x1f, 0xe5, 0xf2, 0xc5, 0xf9, 0xd4, 0xf2, 0x85,
-	0xd2, 0xa4, 0xf4, 0x5a, 0xa5, 0xc9, 0x3a, 0xde, 0xde, 0x87, 0xfe, 0x89, 0x17, 0xd8, 0x97, 0x87,
-	0x7e, 0xce, 0x1b, 0x06, 0xd4, 0x99, 0x9f, 0x77, 0x46, 0xd2, 0x35, 0xdf, 0x81, 0xde, 0x71, 0x60,
-	0x53, 0xef, 0x24, 0x88, 0x7d, 0x91, 0x7a, 0x01, 0xbf, 0xbb, 0x69, 0x53, 0xd5, 0x31, 0xdf, 0x87,
-	0xae, 0x4e, 0xd1, 0xfe, 0x79, 0x90, 0x30, 0x63, 0x96, 0xcc, 0x4b, 0xc5, 0x42, 0xdf, 0x3c, 0x86,
-	0x5e, 0x66, 0xae, 0xe6, 0x7d, 0x07, 0x6a, 0x4a, 0xad, 0xcf, 0xd6, 0x4b, 0x5f, 0xaf, 0xca, 0xd2,
-	0xd2, 0xea, 0x0d, 0x87, 0x5a, 0x40, 0xf7, 0x14, 0xbf, 0x7f, 0x1e, 0xfa, 0x57, 0x6a, 0xb2, 0x23,
-	0x20, 0xea, 0x8b, 0xe8, 0x94, 0xf9, 0x57, 0x2e, 0x0f, 0x7c, 0x2c, 0xae, 0x4b, 0xba, 0x84, 0x49,
-	0x26, 0x4e, 0x07, 0x25, 0x16, 0x56, 0x3f, 0x5c, 0x15, 0x6d, 0xf4, 0x21, 0x64, 0x5f, 0x57, 0x64,
-	0xaa, 0xe1, 0x6c, 0x11, 0x08, 0x36, 0xa5, 0x8e, 0x93, 0x44, 0x0b, 0x28, 0xd1, 0xbe, 0xe3, 0xf0,
-	0xbd, 0xff, 0x94, 0xa1, 0xfe, 0x99, 0x22, 0x70, 0xf2, 0x29, 0x74, 0x0a, 0xe9, 0x9a, 0xbc, 0x81,
-	0x65, 0xdd, 0x6a, 0x71, 0x30, 0xb8, 0xbd, 0x26, 0x56, 0xe7, 0xfa, 0x00, 0xda, 0xf9, 0x64, 0x4c,
-	0x30, 0xf1, 0xe2, 0xb7, 0xde, 0x01, 0xce, 0xb4, 0x9e, 0xa9, 0xcf, 0x60, 0x67, 0x53, 0x9a, 0x24,
-	0xf7, 0xb2, 0x15, 0xd6, 0x53, 0xf4, 0xe0, 0xcd, 0x9b, 0xb4, 0x49, 0x7a, 0xad, 0x1f, 0x78, 0x8c,
-	0xfa, 0x71, 0x98, 0xdf, 0x41, 0xd6, 0x24, 0x8f, 0xa1, 0x53, 0x48, 0x14, 0xea, 0x9c, 0x6b, 0xb9,
-	0x23, 0x3f, 0xe4, 0x21, 0x54, 0x31, 0x39, 0x91, 0x4e, 0x21, 0x4b, 0x0e, 0xba, 0x69, 0x57, 0xad,
-	0x3d, 0x84, 0x2d, 0xfc, 0x02, 0x98, 0x5b, 0x18, 0x47, 0xa4, 0x99, 0x6b, 0xef, 0xdf, 0x25, 0xa8,
-	0x27, 0x5f, 0x85, 0x1f, 0xc3, 0x96, 0xcc, 0x01, 0xe4, 0x56, 0x8e, 0x46, 0x93, 0xfc, 0x31, 0xd8,
-	0x59, 0x11, 0xaa, 0x05, 0xc6, 0x50, 0x79, 0xce, 0x04, 0x21, 0x39, 0xa5, 0x4e, 0x06, 0x83, 0x5b,
-	0x45, 0x59, 0x6a, 0x7f, 0x1a, 0x17, 0xed, 0x35, 0x97, 0x17, 0xec, 0x53, 0x96, 0xfe, 0x08, 0x6a,
-	0x8a, 0x65, 0x95, 0x53, 0xd6, 0xf8, 0x59, 0x5d, 0xfe, 0x3a, 0x1f, 0xef, 0xfd, 0x73, 0x0b, 0xe0,
-	0x6c, 0x19, 0x09, 0xb6, 0xf8, 0x8d, 0xcb, 0x5e, 0x92, 0x47, 0xd0, 0x7b, 0xc6, 0xce, 0x69, 0xec,
-	0x09, 0x7c, 0xaa, 0x49, 0x36, 0xc9, 0xf9, 0x04, 0x0b, 0xbe, 0x94, 0xac, 0x1f, 0x42, 0xeb, 0x84,
-	0x5e, 0xbf, 0xda, 0xee, 0x53, 0xe8, 0x14, 0x38, 0x58, 0x6f, 0x71, 0x95, 0xd5, 0xf5, 0x16, 0xd7,
-	0xd9, 0xfa, 0x21, 0xd4, 0x35, 0x33, 0xe7, 0xd7, 0xc0, 0x1c, 0x56, 0x60, 0xec, 0x9f, 0x43, 0x6f,
-	0x85, 0x97, 0xf3, 0xf6, 0xf8, 0x39, 0x64, 0x23, 0x6f, 0x3f, 0x95, 0xaf, 0x9d, 0x22, 0x37, 0xe7,
-	0x07, 0xea, 0x97, 0xd7, 0x26, 0xf2, 0x7e, 0x5e, 0x7c, 0x27, 0xe1, 0x13, 0xd5, 0x58, 0xa5, 0xcf,
-	0x84, 0xbc, 0x07, 0x77, 0x36, 0x69, 0xd2, 0x10, 0xcc, 0x33, 0xe8, 0x5a, 0x08, 0xae, 0xd3, 0xeb,
-	0x7b, 0x00, 0x19, 0x89, 0xe6, 0xed, 0x11, 0x1e, 0xab, 0xfc, 0xfa, 0x21, 0x40, 0x46, 0x8d, 0x0a,
-	0x55, 0x45, 0x66, 0x55, 0xc3, 0x56, 0xe9, 0xf3, 0x11, 0x34, 0x53, 0x3a, 0xcb, 0xaf, 0x81, 0x13,
-	0x14, 0xd9, 0xf1, 0xb3, 0x47, 0xbf, 0x1f, 0xcd, 0x5d, 0x71, 0x11, 0xcf, 0xc6, 0x76, 0xb0, 0xd8,
-	0xbd, 0xa0, 0xd1, 0x85, 0x6b, 0x07, 0x3c, 0xdc, 0xbd, 0x92, 0x60, 0xda, 0x2d, 0xfc, 0xb4, 0x9a,
-	0xd5, 0xf0, 0xa1, 0xf7, 0xe4, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x0c, 0x01, 0xf3, 0xcc,
-	0x1a, 0x00, 0x00,
+	0x0c, 0x33, 0x36, 0x68, 0xd1, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
+	0x6b, 0x09, 0xc7, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
+	0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xe6, 0x2e, 0x77, 0x29, 0x57, 0xee, 0xf3, 0x0a, 0xb9,
+	0xcc, 0x33, 0xa4, 0xa6, 0x67, 0xf6, 0x04, 0x80, 0x96, 0x5c, 0xe5, 0xdc, 0xcd, 0x74, 0xf7, 0x9c,
+	0x7a, 0xbe, 0xfe, 0xba, 0x67, 0x17, 0xee, 0x47, 0xce, 0xd5, 0x5e, 0xe8, 0xc5, 0x73, 0xd7, 0xdf,
+	0x0b, 0x67, 0x7b, 0x33, 0x6a, 0x5f, 0x31, 0xdf, 0x19, 0x87, 0x3c, 0x10, 0x01, 0x29, 0x87, 0xb3,
+	0xc1, 0xc3, 0x79, 0x10, 0xcc, 0x3d, 0xb6, 0x87, 0x92, 0x59, 0x7c, 0xb1, 0x27, 0xdc, 0x05, 0x8b,
+	0x04, 0x5d, 0x84, 0xca, 0x68, 0x30, 0x90, 0x33, 0x78, 0xc1, 0xdc, 0xb5, 0xa9, 0xb7, 0xe7, 0x3a,
+	0xcc, 0x17, 0xae, 0x58, 0x6a, 0x9d, 0x91, 0xd7, 0xa9, 0x55, 0x94, 0xc6, 0xac, 0x43, 0xf5, 0x68,
+	0x11, 0x8a, 0xa5, 0x39, 0x84, 0xda, 0xe7, 0x8c, 0x3a, 0x8c, 0x93, 0xbb, 0x50, 0xbb, 0xc4, 0x96,
+	0x51, 0x1a, 0x56, 0x46, 0x4d, 0x4b, 0xf7, 0xcc, 0x3f, 0x00, 0x9c, 0xc9, 0x31, 0x47, 0x9c, 0x07,
+	0x9c, 0xdc, 0x83, 0x06, 0xe3, 0x7c, 0x2a, 0x96, 0x21, 0x33, 0x4a, 0xc3, 0xd2, 0xa8, 0x63, 0xd5,
+	0x19, 0xe7, 0x93, 0x65, 0xc8, 0xc8, 0xff, 0x81, 0x6c, 0x4e, 0x17, 0xd1, 0xdc, 0x28, 0x0f, 0x4b,
+	0x72, 0x06, 0xc6, 0xf9, 0x69, 0x34, 0x4f, 0xc6, 0xd8, 0x81, 0xc3, 0x8c, 0xca, 0xb0, 0x34, 0xaa,
+	0xe0, 0x98, 0xc3, 0xc0, 0x61, 0xe6, 0x5f, 0x4a, 0x50, 0x3d, 0xa3, 0xe2, 0x32, 0x22, 0x04, 0xb6,
+	0x78, 0x10, 0x08, 0xbd, 0x38, 0xb6, 0xc9, 0x08, 0x7a, 0xb1, 0x4f, 0x63, 0x71, 0x29, 0x4f, 0x65,
+	0x53, 0xc1, 0x1c, 0xa3, 0x8c, 0xea, 0x55, 0x31, 0x79, 0x13, 0x3a, 0x5e, 0x60, 0x53, 0x6f, 0x1a,
+	0x89, 0x80, 0xd3, 0xb9, 0x5c, 0x47, 0xda, 0xb5, 0x51, 0x78, 0xae, 0x64, 0x64, 0x17, 0xfa, 0x11,
+	0xa3, 0xde, 0xf4, 0x05, 0xa7, 0x61, 0x6a, 0xb8, 0xa5, 0x26, 0x94, 0x8a, 0x6f, 0x38, 0x0d, 0xb5,
+	0xad, 0xf9, 0xf7, 0x1a, 0xd4, 0x2d, 0xf6, 0xa7, 0x98, 0x45, 0x82, 0x74, 0xa1, 0xec, 0x3a, 0x78,
+	0xda, 0xa6, 0x55, 0x76, 0x1d, 0x32, 0x06, 0x62, 0xb1, 0xd0, 0x93, 0x4b, 0xbb, 0x81, 0x7f, 0xe8,
+	0xc5, 0x91, 0x60, 0x5c, 0x9f, 0x79, 0x83, 0x86, 0x3c, 0x80, 0x66, 0x10, 0x32, 0x8e, 0x32, 0x74,
+	0x40, 0xd3, 0xca, 0x04, 0xf2, 0xe0, 0x21, 0x15, 0x97, 0xc6, 0x16, 0x2a, 0xb0, 0x2d, 0x65, 0x0e,
+	0x15, 0xd4, 0xa8, 0x2a, 0x99, 0x6c, 0x13, 0x13, 0x6a, 0x11, 0xb3, 0x39, 0x13, 0x46, 0x6d, 0x58,
+	0x1a, 0xb5, 0xf6, 0x61, 0x1c, 0xce, 0xc6, 0xe7, 0x28, 0xb1, 0xb4, 0x86, 0x3c, 0x80, 0x2d, 0xe9,
+	0x17, 0xa3, 0x8e, 0x16, 0x0d, 0x69, 0x71, 0x10, 0x8b, 0x4b, 0x0b, 0xa5, 0x64, 0x1f, 0xea, 0xea,
+	0x4e, 0x23, 0xa3, 0x31, 0xac, 0x8c, 0x5a, 0xfb, 0x86, 0x34, 0xd0, 0xa7, 0x1c, 0x2b, 0x18, 0x44,
+	0x47, 0xbe, 0xe0, 0x4b, 0x2b, 0x31, 0x24, 0x6f, 0x40, 0xdb, 0xf6, 0x5c, 0xe6, 0x8b, 0xa9, 0x08,
+	0xae, 0x98, 0x6f, 0x34, 0x71, 0x47, 0x2d, 0x25, 0x9b, 0x48, 0x11, 0xd9, 0x87, 0xd7, 0xf2, 0x26,
+	0x53, 0x6a, 0xdb, 0x2c, 0x8a, 0x02, 0x6e, 0x00, 0xda, 0xde, 0xc9, 0xd9, 0x1e, 0x68, 0x95, 0x9c,
+	0xd6, 0x71, 0xa3, 0xd0, 0xa3, 0xcb, 0xa9, 0x4f, 0x17, 0xcc, 0x68, 0xa9, 0x69, 0xb5, 0xec, 0x4b,
+	0xba, 0x60, 0xe4, 0x21, 0xb4, 0x16, 0x41, 0xec, 0x8b, 0x69, 0x18, 0xb8, 0xbe, 0x30, 0xda, 0x68,
+	0x01, 0x28, 0x3a, 0x93, 0x12, 0xf2, 0x3a, 0xa8, 0x9e, 0x02, 0x63, 0x47, 0xf9, 0x15, 0x25, 0x08,
+	0xc7, 0x47, 0xd0, 0x55, 0xea, 0x74, 0x3f, 0x5d, 0x34, 0xe9, 0xa0, 0x34, 0xdd, 0xc9, 0x7b, 0xd0,
+	0x44, 0x3c, 0xb8, 0xfe, 0x45, 0x60, 0xf4, 0xd0, 0x6f, 0x77, 0x72, 0x6e, 0x91, 0x98, 0x38, 0xf6,
+	0x2f, 0x02, 0xab, 0xf1, 0x42, 0xb7, 0xc8, 0xc7, 0x70, 0xbf, 0x70, 0x5e, 0xce, 0x16, 0xd4, 0xf5,
+	0x5d, 0x7f, 0x3e, 0x8d, 0x23, 0x16, 0x19, 0xdb, 0x88, 0x70, 0x23, 0x77, 0x6a, 0x2b, 0x31, 0xf8,
+	0x3a, 0x62, 0x11, 0xb9, 0x0f, 0x4d, 0x15, 0xa4, 0x53, 0xd7, 0x31, 0xfa, 0xb8, 0xa5, 0x86, 0x12,
+	0x1c, 0x3b, 0xe4, 0x2d, 0xe8, 0x85, 0x81, 0xe7, 0xda, 0xcb, 0x69, 0x70, 0xcd, 0x38, 0x77, 0x1d,
+	0x66, 0x90, 0x61, 0x69, 0xd4, 0xb0, 0xba, 0x4a, 0xfc, 0x95, 0x96, 0x6e, 0x0a, 0x8d, 0x3b, 0x68,
+	0xb8, 0x16, 0x1a, 0x63, 0x00, 0x3b, 0xf0, 0x7d, 0x66, 0x23, 0xfc, 0x76, 0xf0, 0x84, 0x5d, 0x79,
+	0xc2, 0xc3, 0x54, 0x6a, 0xe5, 0x2c, 0x06, 0x9f, 0x41, 0x3b, 0x0f, 0x05, 0xb2, 0x0d, 0x95, 0x2b,
+	0xb6, 0xd4, 0xf0, 0x97, 0x4d, 0x32, 0x84, 0xea, 0x35, 0xf5, 0x62, 0x86, 0x90, 0xd7, 0x40, 0x54,
+	0x43, 0x2c, 0xa5, 0xf8, 0x45, 0xf9, 0x69, 0xc9, 0xfc, 0x77, 0x15, 0xb6, 0x24, 0xf8, 0xc8, 0x07,
+	0xd0, 0xf1, 0x18, 0x8d, 0xd8, 0x34, 0x08, 0xe5, 0x02, 0x11, 0x4e, 0xd5, 0xda, 0xdf, 0x96, 0xc3,
+	0x4e, 0xa4, 0xe2, 0x2b, 0x25, 0xb7, 0xda, 0x5e, 0xae, 0x27, 0x43, 0xda, 0xf5, 0x05, 0xe3, 0x3e,
+	0xf5, 0xa6, 0x18, 0x0c, 0x2a, 0xc0, 0xda, 0x89, 0xf0, 0x99, 0x0c, 0x8a, 0x55, 0x1c, 0x55, 0xd6,
+	0x71, 0x34, 0x80, 0x06, 0xfa, 0xce, 0x65, 0x91, 0x0e, 0xf6, 0xb4, 0x4f, 0xf6, 0xa1, 0xb1, 0x60,
+	0x82, 0xea, 0x58, 0x93, 0x21, 0x71, 0x37, 0x89, 0x99, 0xf1, 0xa9, 0x56, 0xa8, 0x80, 0x48, 0xed,
+	0xd6, 0x22, 0xa2, 0xb6, 0x1e, 0x11, 0x03, 0x68, 0xa4, 0xa0, 0xab, 0xab, 0x1b, 0x4e, 0xfa, 0x92,
+	0x66, 0x43, 0xc6, 0xdd, 0xc0, 0x31, 0x1a, 0x08, 0x14, 0xdd, 0x93, 0x24, 0xe9, 0xc7, 0x0b, 0x05,
+	0xa1, 0xa6, 0x22, 0x49, 0x3f, 0x5e, 0xac, 0x23, 0x06, 0x56, 0x10, 0xf3, 0x13, 0xa8, 0x52, 0xcf,
+	0xa5, 0x11, 0x86, 0x90, 0xbc, 0x59, 0xcd, 0xf7, 0xe3, 0x03, 0x29, 0xb5, 0x94, 0x92, 0xbc, 0x0f,
+	0x9d, 0x39, 0x0f, 0xe2, 0x70, 0x8a, 0x5d, 0x16, 0x19, 0x6d, 0x3c, 0xed, 0xaa, 0x75, 0x1b, 0x8d,
+	0x0e, 0x94, 0x8d, 0x8c, 0xc0, 0x59, 0x10, 0xfb, 0xce, 0xd4, 0x76, 0x1d, 0x1e, 0x19, 0x1d, 0x74,
+	0x1e, 0xa0, 0xe8, 0x50, 0x4a, 0x64, 0x88, 0xa9, 0x10, 0x48, 0x1d, 0xdc, 0x45, 0x9b, 0x0e, 0x4a,
+	0xcf, 0x12, 0x2f, 0xff, 0x14, 0xfa, 0x49, 0x62, 0xca, 0x2c, 0x7b, 0x68, 0xb9, 0x9d, 0x28, 0x52,
+	0xe3, 0x11, 0x6c, 0xb3, 0x1b, 0x49, 0xa1, 0xae, 0x98, 0x2e, 0xe8, 0xcd, 0x54, 0x08, 0x4f, 0x87,
+	0x54, 0x37, 0x91, 0x9f, 0xd2, 0x9b, 0x89, 0xf0, 0x64, 0xfc, 0xab, 0xd5, 0x31, 0xfe, 0xfb, 0x98,
+	0x8c, 0x9a, 0x28, 0xc1, 0xf8, 0xdf, 0x85, 0xbe, 0x1f, 0x4c, 0x1d, 0x76, 0x41, 0x63, 0x4f, 0xa8,
+	0x75, 0x97, 0x3a, 0x98, 0x7a, 0x7e, 0xf0, 0x4c, 0xc9, 0x71, 0xd9, 0xe5, 0xe0, 0x97, 0xd0, 0x29,
+	0x5c, 0xf7, 0x06, 0xd0, 0xef, 0xe4, 0x41, 0xdf, 0xcc, 0x03, 0xfd, 0x9f, 0x5b, 0x00, 0x78, 0xef,
+	0x6a, 0xe8, 0x6a, 0xb6, 0xc8, 0x83, 0xa1, 0xbc, 0x01, 0x0c, 0x94, 0x33, 0x5f, 0x68, 0xe0, 0xea,
+	0xde, 0xf7, 0x62, 0x36, 0xc9, 0x17, 0xd5, 0x5c, 0xbe, 0x78, 0x07, 0xb6, 0x24, 0x3e, 0x8d, 0x5a,
+	0x46, 0xeb, 0xd9, 0x8e, 0x10, 0xc9, 0x0a, 0xc5, 0x68, 0xb5, 0x16, 0x34, 0xf5, 0xf5, 0xa0, 0xc9,
+	0xa3, 0xb1, 0x51, 0x44, 0xe3, 0x9b, 0xd0, 0xb1, 0x39, 0xc3, 0xdc, 0x35, 0x95, 0xc5, 0x88, 0x46,
+	0x6b, 0x3b, 0x11, 0x4e, 0xdc, 0x05, 0x93, 0xfe, 0x93, 0x17, 0x07, 0xa8, 0x92, 0xcd, 0x8d, 0xf7,
+	0xda, 0xda, 0x78, 0xaf, 0x58, 0x09, 0x78, 0x4c, 0x33, 0x3e, 0xb6, 0x73, 0x51, 0xd3, 0x29, 0x44,
+	0x4d, 0x21, 0x34, 0xba, 0x2b, 0xa1, 0xb1, 0x82, 0xdf, 0xde, 0x1a, 0x7e, 0xdf, 0x80, 0xb6, 0x74,
+	0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6, 0x95, 0x23, 0x52, 0xd9, 0xb1, 0x83, 0xd1, 0x1e, 0xcf,
+	0x66, 0xcb, 0xcb, 0xc0, 0x63, 0x19, 0x61, 0xb7, 0x52, 0xd9, 0xb1, 0x23, 0xf7, 0x8b, 0x08, 0x24,
+	0x88, 0x40, 0x6c, 0x0f, 0x3e, 0x84, 0x66, 0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d,
+	0x27, 0x45, 0x39, 0x78, 0x32, 0x39, 0xc1, 0xc1, 0x15, 0x4b, 0x36, 0x65, 0x39, 0xc1, 0x99, 0xcf,
+	0x5e, 0xd0, 0x99, 0xa7, 0x26, 0x68, 0x58, 0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0,
+	0xaa, 0x62, 0x65, 0x02, 0xf2, 0x11, 0x80, 0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x94, 0x31,
+	0x18, 0xab, 0x1a, 0x73, 0x9c, 0xd4, 0x98, 0xe3, 0x49, 0x52, 0x63, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b,
+	0xbd, 0x0b, 0x35, 0x79, 0x41, 0x93, 0x13, 0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53,
+	0x55, 0xc8, 0xff, 0x94, 0xe8, 0xef, 0x41, 0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f,
+	0x76, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58, 0x14, 0x06, 0x7e, 0xc4, 0x72, 0x55, 0x52, 0xe9, 0xa5,
+	0x55, 0x52, 0x79, 0x63, 0x95, 0x94, 0xd4, 0x5e, 0x95, 0x5c, 0xed, 0x35, 0x80, 0x06, 0x67, 0x8e,
+	0xcb, 0x99, 0x2d, 0x74, 0x9d, 0x96, 0xf6, 0xa5, 0xee, 0x05, 0xe5, 0x32, 0xbd, 0x47, 0x98, 0x43,
+	0x9a, 0x56, 0xda, 0x27, 0x4f, 0xf2, 0xc5, 0x85, 0x2a, 0xdb, 0x76, 0x54, 0x71, 0xa1, 0xb6, 0xbb,
+	0xa1, 0xba, 0x78, 0x3f, 0x2b, 0xd2, 0xea, 0x18, 0xcd, 0xf7, 0xf2, 0x03, 0x36, 0x57, 0x69, 0x3f,
+	0x5a, 0xce, 0xfe, 0xae, 0x0c, 0xdb, 0xab, 0x7b, 0xdb, 0x80, 0xc0, 0x1d, 0xa8, 0xaa, 0xdc, 0xa7,
+	0xe1, 0x2b, 0xd6, 0xb2, 0x5e, 0x65, 0x85, 0xe8, 0x7e, 0xb5, 0x4a, 0x1a, 0x2f, 0x87, 0x5e, 0x91,
+	0x50, 0xde, 0x86, 0x6d, 0xe9, 0xa2, 0x90, 0x39, 0x59, 0x3d, 0xa7, 0x18, 0xb0, 0xa7, 0xe5, 0x69,
+	0x45, 0xb7, 0x0b, 0xfd, 0xc4, 0x34, 0xe3, 0x86, 0x5a, 0xc1, 0xf6, 0x28, 0xa1, 0x88, 0xbb, 0x50,
+	0xbb, 0x08, 0xf8, 0x82, 0x0a, 0x4d, 0x82, 0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64,
+	0x22, 0x94, 0x6f, 0x16, 0x49, 0x3e, 0xe9, 0x7b, 0x02, 0x59, 0xb0, 0x61, 0x35, 0x92, 0x77, 0x84,
+	0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x90, 0x1b, 0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9,
+	0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x39, 0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0x0f, 0xf8, 0x3c, 0x92,
+	0xc9, 0x50, 0xbf, 0x68, 0xa6, 0x3a, 0xfb, 0x74, 0xac, 0xa6, 0x96, 0x1c, 0x3b, 0xe4, 0x11, 0xd4,
+	0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0x6a, 0x5c, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d,
+	0x1f, 0x33, 0x4b, 0x32, 0x92, 0xe8, 0x57, 0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5,
+	0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02, 0x8b, 0xcc, 0xec, 0xe9, 0x68, 0x49, 0x95, 0xf9, 0x33,
+	0xe8, 0x9f, 0x87, 0xcc, 0x76, 0xa9, 0x87, 0xcf, 0x3e, 0xb5, 0xc0, 0x43, 0xa8, 0x4a, 0x27, 0x27,
+	0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72, 0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x8e, 0x6e, 0xdc, 0x48,
+	0x30, 0xdf, 0x66, 0x87, 0x97, 0xcc, 0xbe, 0xfa, 0x11, 0x4f, 0x7e, 0x0d, 0xf7, 0x36, 0xad, 0x90,
+	0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x42, 0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x93,
+	0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34, 0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xed, 0xfe, 0xf8,
+	0x5b, 0x09, 0x9a, 0xe7, 0x4c, 0xc4, 0x21, 0x9e, 0xe5, 0x3e, 0x34, 0x67, 0x3c, 0xb8, 0x62, 0x3c,
+	0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1d, 0xf2, 0x04, 0x6a, 0x87, 0x81, 0x7f, 0xe1, 0xce, 0xf1, 0x11,
+	0xac, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a, 0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x29,
+	0x7c, 0xfd, 0xf5, 0xf1, 0xb3, 0xa4, 0x3a, 0xce, 0x89, 0x06, 0x1f, 0x41, 0x2b, 0x37, 0xf0, 0x07,
+	0xa5, 0xaa, 0xff, 0x07, 0xc0, 0xd5, 0x95, 0x8f, 0xb6, 0xd5, 0x51, 0xf5, 0x48, 0x79, 0xb4, 0x87,
+	0xd0, 0x94, 0x85, 0x98, 0x52, 0x27, 0x49, 0xb2, 0x94, 0x25, 0x49, 0xf3, 0x11, 0xf4, 0x8f, 0xfd,
+	0x6b, 0xea, 0xb9, 0x0e, 0x15, 0xec, 0x0b, 0xb6, 0x44, 0x17, 0xac, 0xed, 0xc0, 0x3c, 0x87, 0xb6,
+	0x7e, 0x95, 0xbf, 0xd2, 0x1e, 0xdb, 0x7a, 0x8f, 0xdf, 0x1f, 0x44, 0x6f, 0x43, 0x4f, 0x4f, 0x7a,
+	0xe2, 0xea, 0x10, 0x92, 0x35, 0x06, 0x67, 0x17, 0xee, 0x8d, 0x9e, 0x5a, 0xf7, 0xcc, 0xa7, 0xb0,
+	0x9d, 0x33, 0x4d, 0x8f, 0x73, 0xc5, 0x96, 0x51, 0xf2, 0xb5, 0x42, 0xb6, 0x13, 0x0f, 0x94, 0x33,
+	0x0f, 0x98, 0xd0, 0xd5, 0x23, 0x9f, 0x33, 0x71, 0xcb, 0xe9, 0xbe, 0x48, 0x37, 0xf2, 0x9c, 0xe9,
+	0xc9, 0x1f, 0x43, 0x95, 0xc9, 0x93, 0xe6, 0xf3, 0x67, 0xde, 0x03, 0x96, 0x52, 0x6f, 0x58, 0xf0,
+	0x69, 0xba, 0xe0, 0x59, 0xac, 0x16, 0x7c, 0xc5, 0xb9, 0xcc, 0x37, 0xd3, 0x6d, 0x9c, 0xc5, 0xe2,
+	0xb6, 0x1b, 0x7d, 0x04, 0x7d, 0x6d, 0xf4, 0x8c, 0x79, 0x4c, 0xb0, 0x5b, 0x8e, 0xf4, 0x18, 0x48,
+	0xc1, 0xec, 0xb6, 0xe9, 0x1e, 0x40, 0x63, 0x32, 0x39, 0x49, 0xb5, 0x45, 0x6e, 0x34, 0x3f, 0x86,
+	0xfe, 0x79, 0xec, 0x04, 0x67, 0xdc, 0xbd, 0x76, 0x3d, 0x36, 0x57, 0x8b, 0x25, 0xc5, 0x6f, 0x29,
+	0x57, 0xfc, 0x6e, 0xcc, 0x46, 0xe6, 0x08, 0x48, 0x61, 0x78, 0x7a, 0x6f, 0x51, 0xec, 0x04, 0x3a,
+	0x84, 0xb1, 0x6d, 0x8e, 0xa0, 0x3d, 0xa1, 0xb2, 0xd8, 0x70, 0x94, 0x8d, 0x01, 0x75, 0xa1, 0xfa,
+	0xda, 0x2c, 0xe9, 0x9a, 0xfb, 0xb0, 0x73, 0x48, 0xed, 0x4b, 0xd7, 0x9f, 0x3f, 0x73, 0x23, 0x59,
+	0x6d, 0xe9, 0x11, 0x03, 0x68, 0x38, 0x5a, 0xa0, 0x87, 0xa4, 0x7d, 0xf3, 0x5d, 0x78, 0x2d, 0xf7,
+	0x49, 0xe8, 0x5c, 0xd0, 0xc4, 0x1f, 0x3b, 0x50, 0x8d, 0x64, 0x0f, 0x47, 0x54, 0x2d, 0xd5, 0x31,
+	0xbf, 0x84, 0x9d, 0x7c, 0x02, 0x96, 0xb5, 0x4f, 0x72, 0x70, 0xac, 0x4a, 0x4a, 0xb9, 0xaa, 0x44,
+	0xfb, 0xac, 0x9c, 0xe5, 0x93, 0x6d, 0xa8, 0xfc, 0xfa, 0x9b, 0x89, 0x06, 0xbb, 0x6c, 0x9a, 0x7f,
+	0x94, 0xcb, 0x17, 0xe7, 0x53, 0xcb, 0x17, 0x4a, 0x93, 0xd2, 0x2b, 0x95, 0x26, 0xeb, 0x78, 0x7b,
+	0x17, 0xfa, 0xa7, 0x5e, 0x60, 0x5f, 0x1d, 0xf9, 0x39, 0x6f, 0x18, 0x50, 0x67, 0x7e, 0xde, 0x19,
+	0x49, 0xd7, 0x7c, 0x0b, 0x7a, 0x27, 0x81, 0x4d, 0xbd, 0xd3, 0x20, 0xf6, 0x45, 0xea, 0x05, 0xfc,
+	0x46, 0xa7, 0x4d, 0x55, 0xc7, 0x7c, 0x17, 0xba, 0x3a, 0x45, 0xfb, 0x17, 0x41, 0xc2, 0x8c, 0x59,
+	0x32, 0x2f, 0x15, 0x0b, 0x7d, 0xf3, 0x04, 0x7a, 0x99, 0xb9, 0x9a, 0xf7, 0x2d, 0xa8, 0x29, 0xb5,
+	0x3e, 0x5b, 0x2f, 0x7d, 0xe9, 0x2a, 0x4b, 0x4b, 0xab, 0x37, 0x1c, 0x6a, 0x01, 0xdd, 0x33, 0xfc,
+	0x56, 0x7a, 0xe4, 0x5f, 0xab, 0xc9, 0x8e, 0x81, 0xa8, 0xaf, 0xa7, 0x53, 0xe6, 0x5f, 0xbb, 0x3c,
+	0xf0, 0xb1, 0xb8, 0x2e, 0xe9, 0x12, 0x26, 0x99, 0x38, 0x1d, 0x94, 0x58, 0x58, 0xfd, 0x70, 0x55,
+	0xb4, 0xd1, 0x87, 0x90, 0x7d, 0x89, 0x91, 0xa9, 0x86, 0xb3, 0x45, 0x20, 0xd8, 0x94, 0x3a, 0x4e,
+	0x12, 0x2d, 0xa0, 0x44, 0x07, 0x8e, 0xc3, 0xf7, 0xff, 0x53, 0x86, 0xfa, 0xa7, 0x8a, 0xc0, 0xc9,
+	0x27, 0xd0, 0x29, 0xa4, 0x6b, 0xf2, 0x1a, 0x96, 0x75, 0xab, 0xc5, 0xc1, 0xe0, 0xee, 0x9a, 0x58,
+	0x9d, 0xeb, 0x3d, 0x68, 0xe7, 0x93, 0x31, 0xc1, 0xc4, 0x8b, 0xdf, 0x85, 0x07, 0x38, 0xd3, 0x7a,
+	0xa6, 0x3e, 0x87, 0x9d, 0x4d, 0x69, 0x92, 0x3c, 0xc8, 0x56, 0x58, 0x4f, 0xd1, 0x83, 0xd7, 0x6f,
+	0xd3, 0x26, 0xe9, 0xb5, 0x7e, 0xe8, 0x31, 0xea, 0xc7, 0x61, 0x7e, 0x07, 0x59, 0x93, 0x3c, 0x81,
+	0x4e, 0x21, 0x51, 0xa8, 0x73, 0xae, 0xe5, 0x8e, 0xfc, 0x90, 0xc7, 0x50, 0xc5, 0xe4, 0x44, 0x3a,
+	0x85, 0x2c, 0x39, 0xe8, 0xa6, 0x5d, 0xb5, 0xf6, 0x10, 0xb6, 0xf0, 0x6b, 0x41, 0x6e, 0x61, 0x1c,
+	0x91, 0x66, 0xae, 0xfd, 0x7f, 0x95, 0xa0, 0x9e, 0x7c, 0x41, 0x7e, 0x02, 0x5b, 0x32, 0x07, 0x90,
+	0x3b, 0x39, 0x1a, 0x4d, 0xf2, 0xc7, 0x60, 0x67, 0x45, 0xa8, 0x16, 0x18, 0x43, 0xe5, 0x39, 0x13,
+	0x84, 0xe4, 0x94, 0x3a, 0x19, 0x0c, 0xee, 0x14, 0x65, 0xa9, 0xfd, 0x59, 0x5c, 0xb4, 0xd7, 0x5c,
+	0x5e, 0xb0, 0x4f, 0x59, 0xfa, 0x43, 0xa8, 0x29, 0x96, 0x55, 0x4e, 0x59, 0xe3, 0x67, 0x75, 0xf9,
+	0xeb, 0x7c, 0xbc, 0xff, 0x8f, 0x2d, 0x80, 0xf3, 0x65, 0x24, 0xd8, 0xe2, 0x37, 0x2e, 0x7b, 0x41,
+	0x76, 0xa1, 0xa7, 0xbf, 0x89, 0xe0, 0x53, 0x4d, 0xb2, 0x49, 0xce, 0x27, 0x58, 0xf0, 0xa5, 0x64,
+	0xfd, 0x18, 0x5a, 0xa7, 0xf4, 0xe6, 0xe5, 0x76, 0x9f, 0x40, 0xa7, 0xc0, 0xc1, 0x7a, 0x8b, 0xab,
+	0xac, 0xae, 0xb7, 0xb8, 0xce, 0xd6, 0x8f, 0xa1, 0xae, 0x99, 0x39, 0xbf, 0x06, 0xe6, 0xb0, 0x02,
+	0x63, 0xff, 0x1c, 0x7a, 0x2b, 0xbc, 0x9c, 0xb7, 0xc7, 0xcf, 0x21, 0x1b, 0x79, 0xfb, 0xa9, 0x7c,
+	0xed, 0x14, 0xb9, 0x39, 0x3f, 0x50, 0xbf, 0xbc, 0x36, 0x91, 0xf7, 0xf3, 0xe2, 0x3b, 0x09, 0x9f,
+	0xa8, 0xc6, 0x2a, 0x7d, 0x26, 0xe4, 0x3d, 0xb8, 0xb7, 0x49, 0x93, 0x86, 0x60, 0x9e, 0x41, 0xd7,
+	0x42, 0x70, 0x9d, 0x5e, 0xdf, 0x01, 0xc8, 0x48, 0x34, 0x6f, 0x8f, 0xf0, 0x58, 0xe5, 0xd7, 0x0f,
+	0x00, 0x32, 0x6a, 0x54, 0xa8, 0x2a, 0x32, 0xab, 0x1a, 0xb6, 0x4a, 0x9f, 0xbb, 0xd0, 0x4c, 0xe9,
+	0x2c, 0xbf, 0x06, 0x4e, 0x50, 0x64, 0xc7, 0x4f, 0x77, 0x7f, 0x3f, 0x9a, 0xbb, 0xe2, 0x32, 0x9e,
+	0x8d, 0xed, 0x60, 0xb1, 0x77, 0x49, 0xa3, 0x4b, 0xd7, 0x0e, 0x78, 0xb8, 0x77, 0x2d, 0xc1, 0xb4,
+	0x57, 0xf8, 0xc1, 0x35, 0xab, 0xe1, 0x43, 0xef, 0xfd, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xbd,
+	0xc6, 0x6e, 0xfa, 0xf8, 0x1a, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
diff --git a/sdk/plugin/pb/backend.proto b/sdk/plugin/pb/backend.proto
index 65f4ef80dc55..ca86c9c13928 100644
--- a/sdk/plugin/pb/backend.proto
+++ b/sdk/plugin/pb/backend.proto
@@ -210,6 +210,9 @@ message Auth {
 
 	// TokenType is the type of token being requested
 	uint32 token_type = 17;
+
+	// Whether the default policy should be added automatically by core
+	bool no_default_policy = 18;
 }
 
 message TokenEntry {
diff --git a/sdk/plugin/pb/translation.go b/sdk/plugin/pb/translation.go
index 3ef85a082145..23c7e718cb88 100644
--- a/sdk/plugin/pb/translation.go
+++ b/sdk/plugin/pb/translation.go
@@ -507,6 +507,7 @@ func LogicalAuthToProtoAuth(a *logical.Auth) (*Auth, error) {
 		Policies:         a.Policies,
 		TokenPolicies:    a.TokenPolicies,
 		IdentityPolicies: a.IdentityPolicies,
+		NoDefaultPolicy:  a.NoDefaultPolicy,
 		Metadata:         a.Metadata,
 		ClientToken:      a.ClientToken,
 		Accessor:         a.Accessor,
@@ -554,6 +555,7 @@ func ProtoAuthToLogicalAuth(a *Auth) (*logical.Auth, error) {
 		Policies:         a.Policies,
 		TokenPolicies:    a.TokenPolicies,
 		IdentityPolicies: a.IdentityPolicies,
+		NoDefaultPolicy:  a.NoDefaultPolicy,
 		Metadata:         a.Metadata,
 		ClientToken:      a.ClientToken,
 		Accessor:         a.Accessor,
diff --git a/vault/external_tests/policy/no_default_test.go b/vault/external_tests/policy/no_default_test.go
new file mode 100644
index 000000000000..86fbc989ea29
--- /dev/null
+++ b/vault/external_tests/policy/no_default_test.go
@@ -0,0 +1,85 @@
+package policy
+
+import (
+	"testing"
+
+	"github.com/go-test/deep"
+	"github.com/hashicorp/go-hclog"
+	"github.com/hashicorp/vault/api"
+	"github.com/hashicorp/vault/builtin/credential/ldap"
+	vaulthttp "github.com/hashicorp/vault/http"
+	"github.com/hashicorp/vault/sdk/logical"
+	"github.com/hashicorp/vault/vault"
+)
+
+func TestNoDefaultPolicy(t *testing.T) {
+	var err error
+	coreConfig := &vault.CoreConfig{
+		DisableMlock: true,
+		DisableCache: true,
+		Logger:       hclog.NewNullLogger(),
+		CredentialBackends: map[string]logical.Factory{
+			"ldap": ldap.Factory,
+		},
+	}
+
+	cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
+		HandlerFunc: vaulthttp.Handler,
+	})
+
+	cluster.Start()
+	defer cluster.Cleanup()
+
+	cores := cluster.Cores
+
+	vault.TestWaitActive(t, cores[0].Core)
+
+	client := cores[0].Client
+
+	err = client.Sys().EnableAuthWithOptions("ldap", &api.EnableAuthOptions{
+		Type: "ldap",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Configure LDAP auth backend
+	secret, err := client.Logical().Write("auth/ldap/config", map[string]interface{}{
+		"url":                     "ldap://ldap.forumsys.com",
+		"userattr":                "uid",
+		"userdn":                  "dc=example,dc=com",
+		"groupdn":                 "dc=example,dc=com",
+		"binddn":                  "cn=read-only-admin,dc=example,dc=com",
+		"token_no_default_policy": true,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Create a local user in LDAP
+	secret, err = client.Logical().Write("auth/ldap/users/tesla", map[string]interface{}{
+		"policies": "foo",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Login with LDAP and create a token
+	secret, err = client.Logical().Write("auth/ldap/login/tesla", map[string]interface{}{
+		"password": "password",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	token := secret.Auth.ClientToken
+
+	// Lookup the token to get the entity ID
+	secret, err = client.Auth().Token().Lookup(token)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if diff := deep.Equal(secret.Data["policies"], []interface{}{"foo"}); diff != nil {
+		t.Fatal(diff)
+	}
+}
diff --git a/vault/request_handling.go b/vault/request_handling.go
index d3e9bb04a603..82fba9d06139 100644
--- a/vault/request_handling.go
+++ b/vault/request_handling.go
@@ -1035,6 +1035,11 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
 		var entity *identity.Entity
 		auth = resp.Auth
 
+		// Only the token store can toggle this off, and that's via a different
+		// path since it's not a login request; it's explicitly disallowed
+		// above
+		auth.Renewable = true
+
 		mEntry := c.router.MatchingMountEntry(ctx, req.Path)
 
 		if auth.Alias != nil &&
@@ -1110,7 +1115,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
 			return nil, nil, ErrInternalError
 		}
 
-		auth.TokenPolicies = policyutil.SanitizePolicies(auth.Policies, policyutil.AddDefaultPolicy)
+		auth.TokenPolicies = policyutil.SanitizePolicies(auth.Policies, !auth.NoDefaultPolicy)
 		allPolicies := policyutil.SanitizePolicies(append(auth.TokenPolicies, identityPolicies[ns.ID]...), policyutil.DoNotAddDefaultPolicy)
 
 		// Prevent internal policies from being assigned to tokens. We check

From 4fdbab1effd3b7b0f860d47936e6b868456a23ef Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Tue, 30 Apr 2019 10:58:16 -0400
Subject: [PATCH 02/12] Add a bunch more token store logic

---
 sdk/helper/tokenhelper/tokenhelper.go |   3 +-
 vault/token_store.go                  | 397 +++++++++++++-------------
 2 files changed, 202 insertions(+), 198 deletions(-)

diff --git a/sdk/helper/tokenhelper/tokenhelper.go b/sdk/helper/tokenhelper/tokenhelper.go
index f5624fc9a190..09e8dcede909 100644
--- a/sdk/helper/tokenhelper/tokenhelper.go
+++ b/sdk/helper/tokenhelper/tokenhelper.go
@@ -93,6 +93,7 @@ func TokenFields() map[string]*framework.FieldSchema {
 
 		"token_type": &framework.FieldSchema{
 			Type:        framework.TypeString,
+			Default:     "default-service",
 			Description: "The type of token to generate, service or batch",
 		},
 
@@ -146,7 +147,7 @@ func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldD
 			tokenType = logical.TokenTypeService
 		case "batch":
 			tokenType = logical.TokenTypeBatch
-		case "default-service":
+		case "", "default", "default-service":
 			tokenType = logical.TokenTypeDefaultService
 		case "default-batch":
 			tokenType = logical.TokenTypeDefaultBatch
diff --git a/vault/token_store.go b/vault/token_store.go
index 31789ca878f2..752b3ec30798 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -32,6 +32,7 @@ import (
 	"github.com/hashicorp/vault/sdk/helper/policyutil"
 	"github.com/hashicorp/vault/sdk/helper/salt"
 	"github.com/hashicorp/vault/sdk/helper/strutil"
+	"github.com/hashicorp/vault/sdk/helper/tokenhelper"
 	"github.com/hashicorp/vault/sdk/logical"
 	"github.com/hashicorp/vault/sdk/plugin/pb"
 	"github.com/mitchellh/mapstructure"
@@ -103,7 +104,7 @@ var (
 )
 
 func (ts *TokenStore) paths() []*framework.Path {
-	return []*framework.Path{
+	p := []*framework.Path{
 		{
 			Pattern: "roles/?$",
 
@@ -126,76 +127,6 @@ func (ts *TokenStore) paths() []*framework.Path {
 			HelpDescription: tokenListAccessorsHelp,
 		},
 
-		{
-			Pattern: "roles/" + framework.GenericNameRegex("role_name"),
-			Fields: map[string]*framework.FieldSchema{
-				"role_name": &framework.FieldSchema{
-					Type:        framework.TypeString,
-					Description: "Name of the role",
-				},
-
-				"allowed_policies": &framework.FieldSchema{
-					Type:        framework.TypeCommaStringSlice,
-					Description: tokenAllowedPoliciesHelp,
-				},
-
-				"disallowed_policies": &framework.FieldSchema{
-					Type:        framework.TypeCommaStringSlice,
-					Description: tokenDisallowedPoliciesHelp,
-				},
-
-				"orphan": &framework.FieldSchema{
-					Type:        framework.TypeBool,
-					Default:     false,
-					Description: tokenOrphanHelp,
-				},
-
-				"period": &framework.FieldSchema{
-					Type:        framework.TypeDurationSecond,
-					Default:     0,
-					Description: tokenPeriodHelp,
-				},
-
-				"path_suffix": &framework.FieldSchema{
-					Type:        framework.TypeString,
-					Default:     "",
-					Description: tokenPathSuffixHelp + pathSuffixSanitize.String(),
-				},
-
-				"explicit_max_ttl": &framework.FieldSchema{
-					Type:        framework.TypeDurationSecond,
-					Default:     0,
-					Description: tokenExplicitMaxTTLHelp,
-				},
-
-				"renewable": &framework.FieldSchema{
-					Type:        framework.TypeBool,
-					Default:     true,
-					Description: tokenRenewableHelp,
-				},
-
-				"bound_cidrs": &framework.FieldSchema{
-					Type:        framework.TypeCommaStringSlice,
-					Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`,
-				},
-
-				"token_type": &framework.FieldSchema{
-					Type:        framework.TypeString,
-					Default:     "service",
-					Description: "The type of token to generate, service or batch",
-				},
-			},
-
-			Callbacks: map[logical.Operation]framework.OperationFunc{
-				logical.ReadOperation:   ts.tokenStoreRoleRead,
-				logical.CreateOperation: ts.tokenStoreRoleCreateUpdate,
-				logical.UpdateOperation: ts.tokenStoreRoleCreateUpdate,
-				logical.DeleteOperation: ts.tokenStoreRoleDelete,
-			},
-
-			ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
-		},
-
 		{
 			Pattern: "create-orphan$",
 
@@ -414,6 +345,74 @@ func (ts *TokenStore) paths() []*framework.Path {
 			HelpDescription: strings.TrimSpace(tokenTidyDesc),
 		},
 	}
+
+	rolesPath := &framework.Path{
+		Pattern: "roles/" + framework.GenericNameRegex("role_name"),
+		Fields: map[string]*framework.FieldSchema{
+			"role_name": &framework.FieldSchema{
+				Type:        framework.TypeString,
+				Description: "Name of the role",
+			},
+
+			"allowed_policies": &framework.FieldSchema{
+				Type:        framework.TypeCommaStringSlice,
+				Description: tokenAllowedPoliciesHelp,
+			},
+
+			"disallowed_policies": &framework.FieldSchema{
+				Type:        framework.TypeCommaStringSlice,
+				Description: tokenDisallowedPoliciesHelp,
+			},
+
+			"orphan": &framework.FieldSchema{
+				Type:        framework.TypeBool,
+				Description: tokenOrphanHelp,
+			},
+
+			"period": &framework.FieldSchema{
+				Type:        framework.TypeDurationSecond,
+				Description: "(DEPRECATED) Use 'token_period' instead. If this and 'token_period' are both specified both will be retained but 'token_period' will take precedence.",
+				Deprecated:  true,
+			},
+
+			"path_suffix": &framework.FieldSchema{
+				Type:        framework.TypeString,
+				Default:     "",
+				Description: tokenPathSuffixHelp + pathSuffixSanitize.String(),
+			},
+
+			"explicit_max_ttl": &framework.FieldSchema{
+				Type:        framework.TypeDurationSecond,
+				Description: "(DEPRECATED) Use 'token_explicit_max_ttl' instead. If this and 'token_explicit_max_ttl' are both specified both will be retained but 'token_explicit_max_ttl' will take precedence.",
+				Deprecated:  true,
+			},
+
+			"renewable": &framework.FieldSchema{
+				Type:        framework.TypeBool,
+				Description: tokenRenewableHelp,
+			},
+
+			"bound_cidrs": &framework.FieldSchema{
+				Type:        framework.TypeCommaStringSlice,
+				Description: "(DEPRECATED) Use 'token_bound_cidrs' instead. If this and 'token_bound_cidrs' are both specified both will be retained but 'token_bound_cidrs' will take precedence.",
+				Deprecated:  true,
+			},
+		},
+
+		Callbacks: map[logical.Operation]framework.OperationFunc{
+			logical.ReadOperation:   ts.tokenStoreRoleRead,
+			logical.CreateOperation: ts.tokenStoreRoleCreateUpdate,
+			logical.UpdateOperation: ts.tokenStoreRoleCreateUpdate,
+			logical.DeleteOperation: ts.tokenStoreRoleDelete,
+		},
+
+		ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
+	}
+
+	tokenhelper.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy"})
+	p = append(p, rolesPath)
+
+	return p
 }
 
 // LookupToken returns the properties of the token from the token store. This
@@ -581,6 +580,8 @@ func (ts *TokenStore) Salt(ctx context.Context) (*salt.Salt, error) {
 
 // tsRoleEntry contains token store role information
 type tsRoleEntry struct {
+	tokenhelper.TokenParams
+
 	// The name of the role. Embedded so it can be used for pathing
 	Name string `json:"name" mapstructure:"name" structs:"name"`
 
@@ -611,9 +612,6 @@ type tsRoleEntry struct {
 
 	// The set of CIDRs that tokens generated using this role will be bound to
 	BoundCIDRs []*sockaddr.SockAddrMarshaler `json:"bound_cidrs"`
-
-	// The type of token this role should issue
-	TokenType logical.TokenType `json:"token_type" mapstructure:"token_type"`
 }
 
 type accessorEntry struct {
@@ -2284,7 +2282,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
 		// isn't in the disallowed list, add it. This is in line with the idea
 		// that roles, when allowed/disallowed ar set, allow a subset of
 		// policies to be set disjoint from the parent token's policies.
-		if !data.NoDefaultPolicy && !strutil.StrListContains(role.DisallowedPolicies, "default") {
+		if !data.NoDefaultPolicy && !role.TokenNoDefaultPolicy && !strutil.StrListContains(role.DisallowedPolicies, "default") {
 			localAddDefault = true
 		}
 
@@ -2406,8 +2404,8 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
 			te.Parent = ""
 		}
 
-		if len(role.BoundCIDRs) > 0 {
-			te.BoundCIDRs = role.BoundCIDRs
+		if len(role.TokenBoundCIDRs) > 0 {
+			te.BoundCIDRs = role.TokenBoundCIDRs
 		}
 
 	case data.NoParent:
@@ -2501,24 +2499,24 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
 	// in role. Batch tokens will error out if not set via role, but here we
 	// need to explicitly check
 	if role != nil && te.Type != logical.TokenTypeBatch {
-		if role.ExplicitMaxTTL != 0 {
+		if role.TokenExplicitMaxTTL != 0 {
 			switch {
 			case explicitMaxTTLToUse == 0:
-				explicitMaxTTLToUse = role.ExplicitMaxTTL
+				explicitMaxTTLToUse = role.TokenExplicitMaxTTL
 			default:
-				if role.ExplicitMaxTTL < explicitMaxTTLToUse {
-					explicitMaxTTLToUse = role.ExplicitMaxTTL
+				if role.TokenExplicitMaxTTL < explicitMaxTTLToUse {
+					explicitMaxTTLToUse = role.TokenExplicitMaxTTL
 				}
 				resp.AddWarning(fmt.Sprintf("Explicit max TTL specified both during creation call and in role; using the lesser value of %d seconds", int64(explicitMaxTTLToUse.Seconds())))
 			}
 		}
-		if role.Period != 0 {
+		if role.TokenPeriod != 0 {
 			switch {
 			case periodToUse == 0:
-				periodToUse = role.Period
+				periodToUse = role.TokenPeriod
 			default:
-				if role.Period < periodToUse {
-					periodToUse = role.Period
+				if role.TokenPeriod < periodToUse {
+					periodToUse = role.TokenPeriod
 				}
 				resp.AddWarning(fmt.Sprintf("Period specified both during creation call and in role; using the lesser value of %d seconds", int64(periodToUse.Seconds())))
 			}
@@ -2872,8 +2870,8 @@ func (ts *TokenStore) authRenew(ctx context.Context, req *logical.Request, d *fr
 		return nil, fmt.Errorf("original token role %q could not be found, not renewing", te.Role)
 	}
 
-	req.Auth.Period = role.Period
-	req.Auth.ExplicitMaxTTL = role.ExplicitMaxTTL
+	req.Auth.Period = role.TokenPeriod
+	req.Auth.ExplicitMaxTTL = role.TokenExplicitMaxTTL
 	return &logical.Response{Auth: req.Auth}, nil
 }
 
@@ -2900,6 +2898,18 @@ func (ts *TokenStore) tokenStoreRole(ctx context.Context, name string) (*tsRoleE
 		result.TokenType = logical.TokenTypeDefaultService
 	}
 
+	// Token field upgrades. We preserve the original value for read
+	// compatibility.
+	if result.Period > 0 && result.TokenPeriod == 0 {
+		result.TokenPeriod = result.Period
+	}
+	if result.ExplicitMaxTTL > 0 && result.TokenExplicitMaxTTL == 0 {
+		result.TokenExplicitMaxTTL = result.ExplicitMaxTTL
+	}
+	if len(result.BoundCIDRs) > 0 && len(result.TokenBoundCIDRs) == 0 {
+		result.TokenBoundCIDRs = result.BoundCIDRs
+	}
+
 	return &result, nil
 }
 
@@ -2947,18 +2957,29 @@ func (ts *TokenStore) tokenStoreRoleRead(ctx context.Context, req *logical.Reque
 
 	resp := &logical.Response{
 		Data: map[string]interface{}{
-			"period":              int64(role.Period.Seconds()),
-			"explicit_max_ttl":    int64(role.ExplicitMaxTTL.Seconds()),
-			"disallowed_policies": role.DisallowedPolicies,
-			"allowed_policies":    role.AllowedPolicies,
-			"name":                role.Name,
-			"orphan":              role.Orphan,
-			"path_suffix":         role.PathSuffix,
-			"renewable":           role.Renewable,
-			"token_type":          role.TokenType.String(),
+			"token_period":           int64(role.TokenPeriod.Seconds()),
+			"token_explicit_max_ttl": int64(role.TokenExplicitMaxTTL.Seconds()),
+			"disallowed_policies":    role.DisallowedPolicies,
+			"allowed_policies":       role.AllowedPolicies,
+			"name":                   role.Name,
+			"orphan":                 role.Orphan,
+			"path_suffix":            role.PathSuffix,
+			"renewable":              role.Renewable,
+			"token_type":             role.TokenType.String(),
 		},
 	}
 
+	if role.Period > 0 {
+		resp.Data["period"] = int64(role.Period.Seconds())
+	}
+
+	if role.ExplicitMaxTTL > 0 {
+		resp.Data["explicit_max_ttl"] = int64(role.ExplicitMaxTTL.Seconds())
+	}
+
+	if len(role.TokenBoundCIDRs) > 0 {
+		resp.Data["token_bound_cidrs"] = role.TokenBoundCIDRs
+	}
 	if len(role.BoundCIDRs) > 0 {
 		resp.Data["bound_cidrs"] = role.BoundCIDRs
 	}
@@ -2997,140 +3018,122 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 		}
 	}
 
-	// In this series of blocks, if we do not find a user-provided value and
-	// it's a creation operation, we call data.Get to get the appropriate
-	// default
+	// First parse fields not duplicated by the token helper
+	{
+		orphanInt, ok := data.GetOk("orphan")
+		if ok {
+			entry.Orphan = orphanInt.(bool)
+		} else if req.Operation == logical.CreateOperation {
+			entry.Orphan = data.Get("orphan").(bool)
+		}
+
+		renewableInt, ok := data.GetOk("renewable")
+		if ok {
+			entry.Renewable = renewableInt.(bool)
+		} else if req.Operation == logical.CreateOperation {
+			entry.Renewable = data.Get("renewable").(bool)
+		}
+
+		pathSuffixInt, ok := data.GetOk("path_suffix")
+		if ok {
+			pathSuffix := pathSuffixInt.(string)
+			switch {
+			case pathSuffix != "":
+				matched := pathSuffixSanitize.MatchString(pathSuffix)
+				if !matched {
+					return logical.ErrorResponse(fmt.Sprintf(
+						"given role path suffix contains invalid characters; must match %s",
+						pathSuffixSanitize.String())), nil
+				}
+			}
+			entry.PathSuffix = pathSuffix
+		} else if req.Operation == logical.CreateOperation {
+			entry.PathSuffix = data.Get("path_suffix").(string)
+		}
 
-	orphanInt, ok := data.GetOk("orphan")
-	if ok {
-		entry.Orphan = orphanInt.(bool)
-	} else if req.Operation == logical.CreateOperation {
-		entry.Orphan = data.Get("orphan").(bool)
+		if strings.Contains(entry.PathSuffix, "..") {
+			return logical.ErrorResponse(fmt.Sprintf("error registering path suffix: %s", consts.ErrPathContainsParentReferences)), nil
+		}
+
+		allowedPoliciesRaw, ok := data.GetOk("allowed_policies")
+		if ok {
+			entry.AllowedPolicies = policyutil.SanitizePolicies(allowedPoliciesRaw.([]string), policyutil.DoNotAddDefaultPolicy)
+		} else if req.Operation == logical.CreateOperation {
+			entry.AllowedPolicies = policyutil.SanitizePolicies(data.Get("allowed_policies").([]string), policyutil.DoNotAddDefaultPolicy)
+		}
+
+		disallowedPoliciesRaw, ok := data.GetOk("disallowed_policies")
+		if ok {
+			entry.DisallowedPolicies = strutil.RemoveDuplicates(disallowedPoliciesRaw.([]string), true)
+		} else if req.Operation == logical.CreateOperation {
+			entry.DisallowedPolicies = strutil.RemoveDuplicates(data.Get("disallowed_policies").([]string), true)
+		}
 	}
 
-	periodInt, ok := data.GetOk("period")
-	if ok {
-		entry.Period = time.Second * time.Duration(periodInt.(int))
-	} else if req.Operation == logical.CreateOperation {
-		entry.Period = time.Second * time.Duration(data.Get("period").(int))
+	// Next parse token fields from the helper
+	if err := entry.ParseTokenFields(req, data); err != nil {
+		return logical.ErrorResponse(errwrap.Wrapf("error parsing role fields: {{err}}", err).Error()), nil
 	}
 
-	renewableInt, ok := data.GetOk("renewable")
-	if ok {
-		entry.Renewable = renewableInt.(bool)
-	} else if req.Operation == logical.CreateOperation {
-		entry.Renewable = data.Get("renewable").(bool)
+	// Now handle backwards compat. Prefer token_ fields over others if both
+	// are set. We set the original fields here so that on read of token role
+	// we can return the same values that were set.
+	periodRaw, ok := data.GetOk("token_period")
+	if !ok {
+		periodRaw, ok = data.GetOk("period")
+		if ok {
+			entry.Period = time.Second * time.Duration(periodRaw.(int))
+		}
 	}
 
-	boundCIDRsRaw, ok := data.GetOk("bound_cidrs")
-	if ok {
-		boundCIDRs := boundCIDRsRaw.([]string)
-		if len(boundCIDRs) == 0 {
-			entry.BoundCIDRs = nil
-		} else {
-			var parsedCIDRs []*sockaddr.SockAddrMarshaler
-			for _, v := range boundCIDRs {
-				parsedCIDR, err := sockaddr.NewSockAddr(v)
-				if err != nil {
-					return logical.ErrorResponse(errwrap.Wrapf(fmt.Sprintf("invalid value %q when parsing bound cidrs: {{err}}", v), err).Error()), nil
-				}
-				parsedCIDRs = append(parsedCIDRs, &sockaddr.SockAddrMarshaler{parsedCIDR})
+	boundCIDRsRaw, ok := data.GetOk("token_bound_cidrs")
+	if !ok {
+		boundCIDRsRaw, ok = data.GetOk("bound_cidrs")
+		if ok {
+			boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
+			if err != nil {
+				return logical.ErrorResponse(errwrap.Wrapf("error parsing bound_cidrs: {{err}}", err).Error()), nil
 			}
-			entry.BoundCIDRs = parsedCIDRs
+			entry.BoundCIDRs = boundCIDRs
 		}
 	}
 
 	var resp *logical.Response
 
-	explicitMaxTTLInt, ok := data.GetOk("explicit_max_ttl")
-	if ok {
-		entry.ExplicitMaxTTL = time.Second * time.Duration(explicitMaxTTLInt.(int))
-	} else if req.Operation == logical.CreateOperation {
-		entry.ExplicitMaxTTL = time.Second * time.Duration(data.Get("explicit_max_ttl").(int))
+	finalExplicitMaxTTL := entry.TokenExplicitMaxTTL
+	explicitMaxTTLRaw, ok := data.GetOk("token_explicit_max_ttl")
+	if !ok {
+		explicitMaxTTLRaw, ok = data.GetOk("explicit_max_ttl")
+		if ok {
+			entry.ExplicitMaxTTL = time.Second * time.Duration(explicitMaxTTLRaw.(int))
+		}
+		finalExplicitMaxTTL = entry.ExplicitMaxTTL
 	}
-	if entry.ExplicitMaxTTL != 0 {
+	if finalExplicitMaxTTL != 0 {
 		sysView := ts.System()
 
-		if sysView.MaxLeaseTTL() != time.Duration(0) && entry.ExplicitMaxTTL > sysView.MaxLeaseTTL() {
+		if sysView.MaxLeaseTTL() != time.Duration(0) && finalExplicitMaxTTL > sysView.MaxLeaseTTL() {
 			if resp == nil {
 				resp = &logical.Response{}
 			}
 			resp.AddWarning(fmt.Sprintf(
 				"Given explicit max TTL of %d is greater than system/mount allowed value of %d seconds; until this is fixed attempting to create tokens against this role will result in an error",
-				int64(entry.ExplicitMaxTTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
-		}
-	}
-
-	pathSuffixInt, ok := data.GetOk("path_suffix")
-	if ok {
-		pathSuffix := pathSuffixInt.(string)
-		switch {
-		case pathSuffix != "":
-			matched := pathSuffixSanitize.MatchString(pathSuffix)
-			if !matched {
-				return logical.ErrorResponse(fmt.Sprintf(
-					"given role path suffix contains invalid characters; must match %s",
-					pathSuffixSanitize.String())), nil
-			}
-		}
-		entry.PathSuffix = pathSuffix
-	} else if req.Operation == logical.CreateOperation {
-		entry.PathSuffix = data.Get("path_suffix").(string)
-	}
-
-	if strings.Contains(entry.PathSuffix, "..") {
-		return logical.ErrorResponse(fmt.Sprintf("error registering path suffix: %s", consts.ErrPathContainsParentReferences)), nil
-	}
-
-	allowedPoliciesRaw, ok := data.GetOk("allowed_policies")
-	if ok {
-		entry.AllowedPolicies = policyutil.SanitizePolicies(allowedPoliciesRaw.([]string), policyutil.DoNotAddDefaultPolicy)
-	} else if req.Operation == logical.CreateOperation {
-		entry.AllowedPolicies = policyutil.SanitizePolicies(data.Get("allowed_policies").([]string), policyutil.DoNotAddDefaultPolicy)
-	}
-
-	disallowedPoliciesRaw, ok := data.GetOk("disallowed_policies")
-	if ok {
-		entry.DisallowedPolicies = strutil.RemoveDuplicates(disallowedPoliciesRaw.([]string), true)
-	} else if req.Operation == logical.CreateOperation {
-		entry.DisallowedPolicies = strutil.RemoveDuplicates(data.Get("disallowed_policies").([]string), true)
-	}
-
-	tokenType := entry.TokenType
-	if tokenType == logical.TokenTypeDefault {
-		tokenType = logical.TokenTypeDefaultService
-	}
-	tokenTypeRaw, ok := data.GetOk("token_type")
-	if ok {
-		tokenTypeStr := tokenTypeRaw.(string)
-		switch tokenTypeStr {
-		case "service":
-			tokenType = logical.TokenTypeService
-		case "batch":
-			tokenType = logical.TokenTypeBatch
-		case "default-service":
-			tokenType = logical.TokenTypeDefaultService
-		case "default-batch":
-			tokenType = logical.TokenTypeDefaultBatch
-		default:
-			return logical.ErrorResponse(fmt.Sprintf("invalid 'token_type' value %q", tokenTypeStr)), nil
+				int64(finalExplicitMaxTTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
 		}
-	} else if req.Operation == logical.CreateOperation {
-		tokenType = logical.TokenTypeDefaultService
 	}
-	entry.TokenType = tokenType
 
+	// Run validity checks on token type
 	if entry.TokenType == logical.TokenTypeBatch {
 		if !entry.Orphan {
 			return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate non-orphan tokens"), nil
 		}
-		if entry.Period != 0 {
+		if entry.Period != 0 || entry.TokenPeriod != 0 {
 			return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate periodic tokens"), nil
 		}
 		if entry.Renewable {
 			return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate renewable tokens"), nil
 		}
-		if entry.ExplicitMaxTTL != 0 {
+		if entry.ExplicitMaxTTL != 0 || entry.TokenExplicitMaxTTL != 0 {
 			return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate tokens with an explicit max TTL"), nil
 		}
 	}

From 7c56432b6a7f5b90a13a3a64c11294923c6c4b6d Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Tue, 30 Apr 2019 11:28:39 -0400
Subject: [PATCH 03/12] Fix some bugs found in tests

---
 vault/token_store.go | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/vault/token_store.go b/vault/token_store.go
index 752b3ec30798..23cfe818fc81 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -377,7 +377,6 @@ func (ts *TokenStore) paths() []*framework.Path {
 
 			"path_suffix": &framework.FieldSchema{
 				Type:        framework.TypeString,
-				Default:     "",
 				Description: tokenPathSuffixHelp + pathSuffixSanitize.String(),
 			},
 
@@ -389,6 +388,7 @@ func (ts *TokenStore) paths() []*framework.Path {
 
 			"renewable": &framework.FieldSchema{
 				Type:        framework.TypeBool,
+				Default:     true,
 				Description: tokenRenewableHelp,
 			},
 
@@ -3077,12 +3077,15 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 
 	// Now handle backwards compat. Prefer token_ fields over others if both
 	// are set. We set the original fields here so that on read of token role
-	// we can return the same values that were set.
+	// we can return the same values that were set. We clear out the Token*
+	// values because otherwise when we read the role back we'll read stale
+	// data since if they're not emptied they'll take precedence.
 	periodRaw, ok := data.GetOk("token_period")
 	if !ok {
 		periodRaw, ok = data.GetOk("period")
 		if ok {
 			entry.Period = time.Second * time.Duration(periodRaw.(int))
+			entry.TokenPeriod = 0
 		}
 	}
 
@@ -3095,6 +3098,7 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 				return logical.ErrorResponse(errwrap.Wrapf("error parsing bound_cidrs: {{err}}", err).Error()), nil
 			}
 			entry.BoundCIDRs = boundCIDRs
+			entry.TokenBoundCIDRs = nil
 		}
 	}
 
@@ -3106,6 +3110,7 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 		explicitMaxTTLRaw, ok = data.GetOk("explicit_max_ttl")
 		if ok {
 			entry.ExplicitMaxTTL = time.Second * time.Duration(explicitMaxTTLRaw.(int))
+			entry.TokenExplicitMaxTTL = 0
 		}
 		finalExplicitMaxTTL = entry.ExplicitMaxTTL
 	}

From 1ac6e1faaf28d654612e197f868b5ace450089f1 Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Tue, 30 Apr 2019 13:30:41 -0400
Subject: [PATCH 04/12] Fix some more tests

---
 .../external_tests/policy/no_default_test.go  |  4 +
 vault/token_store_test.go                     | 92 +++++++++++--------
 2 files changed, 60 insertions(+), 36 deletions(-)

diff --git a/vault/external_tests/policy/no_default_test.go b/vault/external_tests/policy/no_default_test.go
index 86fbc989ea29..a296d1364b1a 100644
--- a/vault/external_tests/policy/no_default_test.go
+++ b/vault/external_tests/policy/no_default_test.go
@@ -1,5 +1,8 @@
 package policy
 
+// This is TODO once tokenhelper is added to ldaputil
+/*
+
 import (
 	"testing"
 
@@ -83,3 +86,4 @@ func TestNoDefaultPolicy(t *testing.T) {
 		t.Fatal(diff)
 	}
 }
+*/
diff --git a/vault/token_store_test.go b/vault/token_store_test.go
index bbfd4566a56c..d7813797e9ae 100644
--- a/vault/token_store_test.go
+++ b/vault/token_store_test.go
@@ -2679,6 +2679,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"allowed_policies": "test1,test2",
 		"path_suffix":      "happenin",
 		"bound_cidrs":      []string{"0.0.0.0/0"},
+		"explicit_max_ttl": "2h",
 	}
 
 	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
@@ -2703,21 +2704,27 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 	}
 
 	expected := map[string]interface{}{
-		"name":                "test",
-		"orphan":              true,
-		"period":              int64(259200),
-		"allowed_policies":    []string{"test1", "test2"},
-		"disallowed_policies": []string{},
-		"path_suffix":         "happenin",
-		"explicit_max_ttl":    int64(0),
-		"renewable":           true,
-		"token_type":          "default-service",
+		"name":                   "test",
+		"orphan":                 true,
+		"token_period":           int64(259200),
+		"period":                 int64(259200),
+		"allowed_policies":       []string{"test1", "test2"},
+		"disallowed_policies":    []string{},
+		"path_suffix":            "happenin",
+		"explicit_max_ttl":       int64(7200),
+		"token_explicit_max_ttl": int64(7200),
+		"renewable":              true,
+		"token_type":             "default-service",
 	}
 
 	if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
 		t.Fatal("unexpected bound cidrs")
 	}
 	delete(resp.Data, "bound_cidrs")
+	if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
+		t.Fatal("unexpected bound cidrs")
+	}
+	delete(resp.Data, "token_bound_cidrs")
 
 	if diff := deep.Equal(expected, resp.Data); diff != nil {
 		t.Fatal(diff)
@@ -2731,6 +2738,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"allowed_policies": "test3",
 		"path_suffix":      "happenin",
 		"renewable":        false,
+		"explicit_max_ttl": "80h",
 	}
 
 	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
@@ -2754,21 +2762,27 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 	}
 
 	expected = map[string]interface{}{
-		"name":                "test",
-		"orphan":              true,
-		"period":              int64(284400),
-		"allowed_policies":    []string{"test3"},
-		"disallowed_policies": []string{},
-		"path_suffix":         "happenin",
-		"explicit_max_ttl":    int64(0),
-		"renewable":           false,
-		"token_type":          "default-service",
+		"name":                   "test",
+		"orphan":                 true,
+		"period":                 int64(284400),
+		"token_period":           int64(284400),
+		"allowed_policies":       []string{"test3"},
+		"disallowed_policies":    []string{},
+		"path_suffix":            "happenin",
+		"token_explicit_max_ttl": int64(288000),
+		"explicit_max_ttl":       int64(288000),
+		"renewable":              false,
+		"token_type":             "default-service",
 	}
 
 	if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
 		t.Fatal("unexpected bound cidrs")
 	}
 	delete(resp.Data, "bound_cidrs")
+	if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
+		t.Fatal("unexpected bound cidrs")
+	}
+	delete(resp.Data, "token_bound_cidrs")
 
 	if diff := deep.Equal(expected, resp.Data); diff != nil {
 		t.Fatal(diff)
@@ -2797,21 +2811,26 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 	}
 
 	expected = map[string]interface{}{
-		"name":                "test",
-		"orphan":              true,
-		"explicit_max_ttl":    int64(5),
-		"allowed_policies":    []string{"test3"},
-		"disallowed_policies": []string{},
-		"path_suffix":         "happenin",
-		"period":              int64(0),
-		"renewable":           false,
-		"token_type":          "default-service",
+		"name":                   "test",
+		"orphan":                 true,
+		"explicit_max_ttl":       int64(5),
+		"token_explicit_max_ttl": int64(5),
+		"allowed_policies":       []string{"test3"},
+		"disallowed_policies":    []string{},
+		"path_suffix":            "happenin",
+		"token_period":           int64(0),
+		"renewable":              false,
+		"token_type":             "default-service",
 	}
 
 	if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
 		t.Fatal("unexpected bound cidrs")
 	}
 	delete(resp.Data, "bound_cidrs")
+	if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
+		t.Fatal("unexpected bound cidrs")
+	}
+	delete(resp.Data, "token_bound_cidrs")
 
 	if diff := deep.Equal(expected, resp.Data); diff != nil {
 		t.Fatal(diff)
@@ -2840,15 +2859,16 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 	}
 
 	expected = map[string]interface{}{
-		"name":                "test",
-		"orphan":              true,
-		"explicit_max_ttl":    int64(5),
-		"allowed_policies":    []string{"test3"},
-		"disallowed_policies": []string{},
-		"path_suffix":         "",
-		"period":              int64(0),
-		"renewable":           false,
-		"token_type":          "default-service",
+		"name":                   "test",
+		"orphan":                 true,
+		"token_explicit_max_ttl": int64(5),
+		"explicit_max_ttl":       int64(5),
+		"allowed_policies":       []string{"test3"},
+		"disallowed_policies":    []string{},
+		"path_suffix":            "",
+		"token_period":           int64(0),
+		"renewable":              false,
+		"token_type":             "default-service",
 	}
 
 	if diff := deep.Equal(expected, resp.Data); diff != nil {

From 4d7ce7e7791af7eb7f9180411a6f45777f88cd08 Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Tue, 30 Apr 2019 17:34:47 -0400
Subject: [PATCH 05/12] More updates

---
 CHANGELOG.md         | 11 +++++++++--
 vault/token_store.go | 17 +++++++++--------
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a48be50fcf2d..ed997e5f996a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,14 @@
 ## Next
 
-CHANGES:
-
+CHANGES/DEPRECATIONS:
+
+ * auth/token: Token store roles use new, common token fields for the values
+   that overlap with other auth backends. `period`, `explicit_max_ttl`, and
+   `bound_cidrs` will continue to work, with priority being given to the
+   `token_` prefixed versions of those parameters. They will also be returned
+   when doing a read on the role if they were used to provide values initially;
+   however, in Vault 1.4 if `period` or `explicit_max_ttl` is zero they will no
+   longer be returned. (`explicit_max_ttl` was already not returned if empty.)
  * autoseal/aws: The user-configured regions on the AWSKMS seal stanza 
    will now be preferred over regions set in the enclosing environment.
    This is a _breaking_ change.
diff --git a/vault/token_store.go b/vault/token_store.go
index 23cfe818fc81..a2e62f418383 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -2955,9 +2955,12 @@ func (ts *TokenStore) tokenStoreRoleRead(ctx context.Context, req *logical.Reque
 		return nil, nil
 	}
 
+	// TODO (1.4): Remove "period" and "explicit_max_ttl" if they're zero
 	resp := &logical.Response{
 		Data: map[string]interface{}{
+			"period":                 int64(role.Period.Seconds()),
 			"token_period":           int64(role.TokenPeriod.Seconds()),
+			"explicit_max_ttl":       int64(role.ExplicitMaxTTL.Seconds()),
 			"token_explicit_max_ttl": int64(role.TokenExplicitMaxTTL.Seconds()),
 			"disallowed_policies":    role.DisallowedPolicies,
 			"allowed_policies":       role.AllowedPolicies,
@@ -2969,14 +2972,6 @@ func (ts *TokenStore) tokenStoreRoleRead(ctx context.Context, req *logical.Reque
 		},
 	}
 
-	if role.Period > 0 {
-		resp.Data["period"] = int64(role.Period.Seconds())
-	}
-
-	if role.ExplicitMaxTTL > 0 {
-		resp.Data["explicit_max_ttl"] = int64(role.ExplicitMaxTTL.Seconds())
-	}
-
 	if len(role.TokenBoundCIDRs) > 0 {
 		resp.Data["token_bound_cidrs"] = role.TokenBoundCIDRs
 	}
@@ -3087,6 +3082,8 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 			entry.Period = time.Second * time.Duration(periodRaw.(int))
 			entry.TokenPeriod = 0
 		}
+	} else {
+		entry.Period = 0
 	}
 
 	boundCIDRsRaw, ok := data.GetOk("token_bound_cidrs")
@@ -3100,6 +3097,8 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 			entry.BoundCIDRs = boundCIDRs
 			entry.TokenBoundCIDRs = nil
 		}
+	} else {
+		entry.BoundCIDRs = nil
 	}
 
 	var resp *logical.Response
@@ -3113,6 +3112,8 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 			entry.TokenExplicitMaxTTL = 0
 		}
 		finalExplicitMaxTTL = entry.ExplicitMaxTTL
+	} else {
+		entry.ExplicitMaxTTL = 0
 	}
 	if finalExplicitMaxTTL != 0 {
 		sysView := ts.System()

From 91e23673e26e62f5a6afe097be0c8e1ea8e1eb5f Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Tue, 30 Apr 2019 18:03:47 -0400
Subject: [PATCH 06/12] Fix test after changes

---
 vault/token_store_test.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/vault/token_store_test.go b/vault/token_store_test.go
index d7813797e9ae..4438e97aa6a4 100644
--- a/vault/token_store_test.go
+++ b/vault/token_store_test.go
@@ -2818,6 +2818,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"allowed_policies":       []string{"test3"},
 		"disallowed_policies":    []string{},
 		"path_suffix":            "happenin",
+		"period":                 int64(0),
 		"token_period":           int64(0),
 		"renewable":              false,
 		"token_type":             "default-service",
@@ -2866,6 +2867,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"allowed_policies":       []string{"test3"},
 		"disallowed_policies":    []string{},
 		"path_suffix":            "",
+		"period":                 int64(0),
 		"token_period":           int64(0),
 		"renewable":              false,
 		"token_type":             "default-service",

From 5e9a4021afbdf6cb615cc2616636613988da39bd Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Wed, 1 May 2019 11:18:08 -0400
Subject: [PATCH 07/12] Add a test of the upgrade and deprecated field
 functionality

---
 vault/token_store.go      |  25 +++-
 vault/token_store_test.go | 244 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 267 insertions(+), 2 deletions(-)

diff --git a/vault/token_store.go b/vault/token_store.go
index a2e62f418383..e8f4d991d05b 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -3070,6 +3070,8 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 		return logical.ErrorResponse(errwrap.Wrapf("error parsing role fields: {{err}}", err).Error()), nil
 	}
 
+	var resp *logical.Response
+
 	// Now handle backwards compat. Prefer token_ fields over others if both
 	// are set. We set the original fields here so that on read of token role
 	// we can return the same values that were set. We clear out the Token*
@@ -3083,6 +3085,13 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 			entry.TokenPeriod = 0
 		}
 	} else {
+		_, ok = data.GetOk("period")
+		if ok {
+			if resp == nil {
+				resp = &logical.Response{}
+			}
+			resp.AddWarning("Both 'token_period' and deprecated 'period' value supplied, ignoring the deprecated value")
+		}
 		entry.Period = 0
 	}
 
@@ -3098,11 +3107,16 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 			entry.TokenBoundCIDRs = nil
 		}
 	} else {
+		_, ok = data.GetOk("bound_cidrs")
+		if ok {
+			if resp == nil {
+				resp = &logical.Response{}
+			}
+			resp.AddWarning("Both 'token_bound_cidrs' and deprecated 'bound_cidrs' value supplied, ignoring the deprecated value")
+		}
 		entry.BoundCIDRs = nil
 	}
 
-	var resp *logical.Response
-
 	finalExplicitMaxTTL := entry.TokenExplicitMaxTTL
 	explicitMaxTTLRaw, ok := data.GetOk("token_explicit_max_ttl")
 	if !ok {
@@ -3113,6 +3127,13 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 		}
 		finalExplicitMaxTTL = entry.ExplicitMaxTTL
 	} else {
+		_, ok = data.GetOk("explicit_max_ttl")
+		if ok {
+			if resp == nil {
+				resp = &logical.Response{}
+			}
+			resp.AddWarning("Both 'token_explicit_max_ttl' and deprecated 'explicit_max_ttl' value supplied, ignoring the deprecated value")
+		}
 		entry.ExplicitMaxTTL = 0
 	}
 	if finalExplicitMaxTTL != 0 {
diff --git a/vault/token_store_test.go b/vault/token_store_test.go
index 4438e97aa6a4..c23ba6bfde1c 100644
--- a/vault/token_store_test.go
+++ b/vault/token_store_test.go
@@ -21,6 +21,8 @@ import (
 	uuid "github.com/hashicorp/go-uuid"
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/helper/locksutil"
+	"github.com/hashicorp/vault/sdk/helper/parseutil"
+	"github.com/hashicorp/vault/sdk/helper/tokenhelper"
 	"github.com/hashicorp/vault/sdk/logical"
 )
 
@@ -3607,6 +3609,248 @@ func TestTokenStore_RoleExplicitMaxTTL(t *testing.T) {
 	}
 }
 
+func TestTokenStore_RoleTokenFields(t *testing.T) {
+	c, _, _ := TestCoreUnsealed(t)
+	//c, _, root := TestCoreUnsealed(t)
+	ts := c.tokenStore
+	rootContext := namespace.RootContext(context.Background())
+
+	boundCIDRs, err := parseutil.ParseAddrs([]string{"127.0.0.1/32"})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// First test the upgrade case. Create a role with values and ensure they
+	// are reflected properly on read.
+	{
+		roleEntry := &tsRoleEntry{
+			Name: "test",
+			TokenParams: tokenhelper.TokenParams{
+				TokenType: logical.TokenTypeBatch,
+			},
+			Period:         time.Second,
+			ExplicitMaxTTL: time.Hour,
+		}
+		roleEntry.BoundCIDRs = boundCIDRs
+		ns := namespace.RootNamespace
+		jsonEntry, err := logical.StorageEntryJSON("test", roleEntry)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if err := ts.rolesView(ns).Put(rootContext, jsonEntry); err != nil {
+			t.Fatal(err)
+		}
+		// Read it back
+		roleEntry, err = ts.tokenStoreRole(rootContext, "test")
+		if err != nil {
+			t.Fatal(err)
+		}
+		expRoleEntry := &tsRoleEntry{
+			Name: "test",
+			TokenParams: tokenhelper.TokenParams{
+				TokenPeriod:         time.Second,
+				TokenExplicitMaxTTL: time.Hour,
+				TokenBoundCIDRs:     boundCIDRs,
+				TokenType:           logical.TokenTypeBatch,
+			},
+			Period:         time.Second,
+			ExplicitMaxTTL: time.Hour,
+			BoundCIDRs:     boundCIDRs,
+		}
+		if diff := deep.Equal(expRoleEntry, roleEntry); diff != nil {
+			t.Fatal(diff)
+		}
+	}
+
+	// Now, read that back through the API and verify we see what we expect
+	{
+		req := logical.TestRequest(t, logical.ReadOperation, "roles/test")
+		resp, err := ts.HandleRequest(rootContext, req)
+		if err != nil {
+			t.Fatalf("err: %v", err)
+		}
+
+		expected := map[string]interface{}{
+			"name":                   "test",
+			"orphan":                 false,
+			"period":                 int64(1),
+			"token_period":           int64(1),
+			"allowed_policies":       []string(nil),
+			"disallowed_policies":    []string(nil),
+			"path_suffix":            "",
+			"token_explicit_max_ttl": int64(3600),
+			"explicit_max_ttl":       int64(3600),
+			"renewable":              false,
+			"token_type":             "batch",
+		}
+
+		if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected bound cidrs: %s", resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "bound_cidrs")
+		if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "token_bound_cidrs")
+
+		if diff := deep.Equal(expected, resp.Data); diff != nil {
+			t.Fatal(diff)
+		}
+	}
+
+	// Put values in just the old locations, but through the API
+	{
+		req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
+		req.Data = map[string]interface{}{
+			"explicit_max_ttl": 7200,
+			"token_type":       "default-batch",
+			"period":           5,
+			"bound_cidrs":      boundCIDRs[0].String(),
+		}
+
+		resp, err := ts.HandleRequest(rootContext, req)
+		if err != nil || (resp != nil && resp.IsError()) {
+			t.Fatalf("err: %v\nresp: %#v", err, resp)
+		}
+		if resp != nil {
+			t.Fatalf("expected a nil response")
+		}
+
+		req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
+		resp, err = ts.HandleRequest(rootContext, req)
+		if err != nil {
+			t.Fatalf("err: %v", err)
+		}
+
+		expected := map[string]interface{}{
+			"name":                   "test",
+			"orphan":                 false,
+			"period":                 int64(5),
+			"token_period":           int64(5),
+			"allowed_policies":       []string(nil),
+			"disallowed_policies":    []string(nil),
+			"path_suffix":            "",
+			"token_explicit_max_ttl": int64(7200),
+			"explicit_max_ttl":       int64(7200),
+			"renewable":              false,
+			"token_type":             "default-batch",
+		}
+
+		if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected bound cidrs: %s", resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "bound_cidrs")
+		if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "token_bound_cidrs")
+
+		if diff := deep.Equal(expected, resp.Data); diff != nil {
+			t.Fatal(diff)
+		}
+	}
+	// Same thing for just the new locations
+	{
+		req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
+		req.Data = map[string]interface{}{
+			"token_explicit_max_ttl": 5200,
+			"token_type":             "default-service",
+			"token_period":           7,
+			"token_bound_cidrs":      boundCIDRs[0].String(),
+		}
+
+		resp, err := ts.HandleRequest(rootContext, req)
+		if err != nil || (resp != nil && resp.IsError()) {
+			t.Fatalf("err: %v\nresp: %#v", err, resp)
+		}
+		if resp != nil {
+			t.Fatalf("expected a nil response")
+		}
+
+		req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
+		resp, err = ts.HandleRequest(rootContext, req)
+		if err != nil {
+			t.Fatalf("err: %v", err)
+		}
+
+		expected := map[string]interface{}{
+			"name":                   "test",
+			"orphan":                 false,
+			"period":                 int64(0),
+			"token_period":           int64(7),
+			"allowed_policies":       []string(nil),
+			"disallowed_policies":    []string(nil),
+			"path_suffix":            "",
+			"token_explicit_max_ttl": int64(5200),
+			"explicit_max_ttl":       int64(0),
+			"renewable":              false,
+			"token_type":             "default-service",
+		}
+
+		if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "token_bound_cidrs")
+
+		if diff := deep.Equal(expected, resp.Data); diff != nil {
+			t.Fatal(diff)
+		}
+	}
+	// Put values in both locations
+	{
+		req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
+		req.Data = map[string]interface{}{
+			"token_explicit_max_ttl": 7200,
+			"explicit_max_ttl":       5200,
+			"token_type":             "service",
+			"token_period":           5,
+			"period":                 1,
+			"token_bound_cidrs":      boundCIDRs[0].String(),
+			"bound_cidrs":            boundCIDRs[0].String(),
+		}
+
+		resp, err := ts.HandleRequest(rootContext, req)
+		if err != nil || (resp != nil && resp.IsError()) {
+			t.Fatalf("err: %v\nresp: %#v", err, resp)
+		}
+		if resp == nil {
+			t.Fatalf("expected a non-nil response")
+		}
+		if len(resp.Warnings) != 3 {
+			t.Fatalf("expected 3 warnings, got %#v", resp.Warnings)
+		}
+
+		req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
+		resp, err = ts.HandleRequest(rootContext, req)
+		if err != nil {
+			t.Fatalf("err: %v", err)
+		}
+
+		expected := map[string]interface{}{
+			"name":                   "test",
+			"orphan":                 false,
+			"period":                 int64(0),
+			"token_period":           int64(5),
+			"allowed_policies":       []string(nil),
+			"disallowed_policies":    []string(nil),
+			"path_suffix":            "",
+			"token_explicit_max_ttl": int64(7200),
+			"explicit_max_ttl":       int64(0),
+			"renewable":              false,
+			"token_type":             "service",
+		}
+
+		if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
+			t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
+		}
+		delete(resp.Data, "token_bound_cidrs")
+
+		if diff := deep.Equal(expected, resp.Data); diff != nil {
+			t.Fatal(diff)
+		}
+	}
+}
+
 func TestTokenStore_Periodic(t *testing.T) {
 	core, _, root := TestCoreUnsealed(t)
 

From d49f4d24d9babb0f0b0fac8c8964775cc417e583 Mon Sep 17 00:00:00 2001
From: Mike Jarmy <mjarmy@gmail.com>
Date: Wed, 12 Jun 2019 10:00:37 -0400
Subject: [PATCH 08/12] minor cleanup of comments

---
 vault/token_store.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/vault/token_store.go b/vault/token_store.go
index e8f4d991d05b..51eddea7e5f4 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -48,7 +48,7 @@ const (
 	accessorPrefix = "accessor/"
 
 	// parentPrefix is the prefix used to store tokens for their
-	// secondar parent based index
+	// secondary parent based index
 	parentPrefix = "parent/"
 
 	// tokenSubPath is the sub-path used for the token store
@@ -539,7 +539,6 @@ func NewTokenStore(ctx context.Context, logger log.Logger, core *Core, config *l
 }
 
 func (ts *TokenStore) Invalidate(ctx context.Context, key string) {
-	//ts.logger.Debug("invalidating key", "key", key)
 
 	switch key {
 	case tokenSubPath + salt.DefaultLocation:

From 8cc0481766b67519791a26b1a94394c22fcbd8b2 Mon Sep 17 00:00:00 2001
From: Lexman <Lexman42@users.noreply.github.com>
Date: Thu, 13 Jun 2019 09:53:36 -0700
Subject: [PATCH 09/12] Alex/add max num uses to tokenhelper v2 (#6701)

---
 sdk/helper/tokenhelper/tokenhelper.go |  17 ++++
 vault/token_store.go                  |  21 ++++-
 vault/token_store_test.go             | 117 ++++++++++++++++++++++++++
 3 files changed, 154 insertions(+), 1 deletion(-)

diff --git a/sdk/helper/tokenhelper/tokenhelper.go b/sdk/helper/tokenhelper/tokenhelper.go
index 09e8dcede909..3edb6ff7ca6e 100644
--- a/sdk/helper/tokenhelper/tokenhelper.go
+++ b/sdk/helper/tokenhelper/tokenhelper.go
@@ -38,6 +38,9 @@ type TokenParams struct {
 
 	// The TTL to user for the token
 	TokenTTL time.Duration `json:"token_ttl" mapstructure:"token_ttl"`
+
+	// The maximum number of times a token issued from this role may be used.
+	TokenNumUses int `json:"token_num_uses" mapstructure:"token_num_uses"`
 }
 
 // AddTokenFields adds fields to an existing role. It panics if it would
@@ -101,6 +104,11 @@ func TokenFields() map[string]*framework.FieldSchema {
 			Type:        framework.TypeDurationSecond,
 			Description: "The initial ttl of the token to generate",
 		},
+
+		"token_num_uses": &framework.FieldSchema{
+			Type:        framework.TypeInt,
+			Description: "The maximum number of times a token may be used, a value of zero means unlimited",
+		},
 	}
 }
 
@@ -167,6 +175,13 @@ func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldD
 		return errors.New("'token_ttl' cannot be greater than 'token_max_ttl'")
 	}
 
+	if tokenNumUses, ok := d.GetOk("token_num_uses"); ok {
+		t.TokenNumUses = tokenNumUses.(int)
+	}
+	if t.TokenNumUses < 0 {
+		return errors.New("'token_num_uses' cannot be negative")
+	}
+
 	return nil
 }
 
@@ -179,6 +194,7 @@ func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
 	m["token_policies"] = t.TokenPolicies
 	m["token_type"] = t.TokenType.String()
 	m["token_ttl"] = t.TokenTTL.Seconds()
+	m["token_num_uses"] = t.TokenNumUses
 }
 
 func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
@@ -190,6 +206,7 @@ func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
 	auth.Policies = t.TokenPolicies
 	auth.TokenType = t.TokenType
 	auth.TTL = t.TokenTTL
+	auth.NumUses = t.TokenNumUses
 }
 
 const (
diff --git a/vault/token_store.go b/vault/token_store.go
index 51eddea7e5f4..d9907d179de7 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -409,7 +409,7 @@ func (ts *TokenStore) paths() []*framework.Path {
 		ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
 	}
 
-	tokenhelper.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy"})
+	tokenhelper.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy", "token_num_uses"})
 	p = append(p, rolesPath)
 
 	return p
@@ -2233,6 +2233,16 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
 			renewable = false
 		}
 
+		// Update te.NumUses which is equal to req.Data["num_uses"] at this point
+		// 0 means unlimited so 1 is actually less than 0
+		switch {
+		case role.TokenNumUses == 0:
+		case te.NumUses == 0:
+			te.NumUses = role.TokenNumUses
+		case role.TokenNumUses < te.NumUses:
+			te.NumUses = role.TokenNumUses
+		}
+
 		if role.PathSuffix != "" {
 			te.Path = fmt.Sprintf("%s/%s", te.Path, role.PathSuffix)
 		}
@@ -2977,6 +2987,9 @@ func (ts *TokenStore) tokenStoreRoleRead(ctx context.Context, req *logical.Reque
 	if len(role.BoundCIDRs) > 0 {
 		resp.Data["bound_cidrs"] = role.BoundCIDRs
 	}
+	if role.TokenNumUses > 0 {
+		resp.Data["token_num_uses"] = role.TokenNumUses
+	}
 
 	return resp, nil
 }
@@ -3148,6 +3161,12 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
 		}
 	}
 
+	// no legacy version without the token_ prefix to check for
+	tokenNumUses, ok := data.GetOk("token_num_uses")
+	if ok {
+		entry.TokenNumUses = tokenNumUses.(int)
+	}
+
 	// Run validity checks on token type
 	if entry.TokenType == logical.TokenTypeBatch {
 		if !entry.Orphan {
diff --git a/vault/token_store_test.go b/vault/token_store_test.go
index c23ba6bfde1c..fd83411245df 100644
--- a/vault/token_store_test.go
+++ b/vault/token_store_test.go
@@ -2682,6 +2682,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"path_suffix":      "happenin",
 		"bound_cidrs":      []string{"0.0.0.0/0"},
 		"explicit_max_ttl": "2h",
+		"token_num_uses":   123,
 	}
 
 	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
@@ -2717,6 +2718,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"token_explicit_max_ttl": int64(7200),
 		"renewable":              true,
 		"token_type":             "default-service",
+		"token_num_uses":         123,
 	}
 
 	if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
@@ -2741,6 +2743,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
 		"path_suffix":      "happenin",
 		"renewable":        false,
 		"explicit_max_ttl": "80h",
+		"token_num_uses":   0,
 	}
 
 	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
@@ -3992,6 +3995,120 @@ func TestTokenStore_Periodic(t *testing.T) {
 	}
 }
 
+func testTokenStore_NumUses_ErrorCheckHelper(t *testing.T, resp *logical.Response, err error) {
+	if err != nil {
+		t.Fatal(err)
+	}
+	if resp == nil {
+		t.Fatal("response was nil")
+	}
+	if resp.Auth == nil {
+		t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
+	}
+	if resp.Auth.ClientToken == "" {
+		t.Fatalf("bad: %#v", resp)
+	}
+}
+
+func testTokenStore_NumUses_SelfLookupHelper(t *testing.T, core *Core, clientToken string, expectedNumUses int) {
+	req := logical.TestRequest(t, logical.ReadOperation, "auth/token/lookup-self")
+	req.ClientToken = clientToken
+	resp, err := core.HandleRequest(namespace.RootContext(nil), req)
+	if err != nil {
+		t.Fatalf("err: %v", err)
+	}
+	// Just used the token, this should decrement the num_uses counter
+	expectedNumUses = expectedNumUses - 1
+	actualNumUses := resp.Data["num_uses"].(int)
+
+	if actualNumUses != expectedNumUses {
+		t.Fatalf("num_uses mismatch (expected %d, got %d)", expectedNumUses, actualNumUses)
+	}
+}
+func TestTokenStore_NumUses(t *testing.T) {
+	core, _, root := TestCoreUnsealed(t)
+	roleNumUses := 10
+	lesserNumUses := 5
+	greaterNumUses := 15
+
+	// Create a test role with limited token_num_uses
+	req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test-limited-uses")
+	req.ClientToken = root
+	req.Data = map[string]interface{}{
+		"token_num_uses": roleNumUses,
+	}
+	resp, err := core.HandleRequest(namespace.RootContext(nil), req)
+	if err != nil || (resp != nil && resp.IsError()) {
+		t.Fatalf("err: %v\nresp: %#v", err, resp)
+	}
+	if resp != nil {
+		t.Fatalf("expected a nil response")
+	}
+
+	// Create a test role with unlimited token_num_uses
+	req.Path = "auth/token/roles/test-unlimited-uses"
+	req.Data = map[string]interface{}{}
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	if err != nil || (resp != nil && resp.IsError()) {
+		t.Fatalf("err: %v\nresp: %#v", err, resp)
+	}
+	if resp != nil {
+		t.Fatalf("expected a nil response")
+	}
+
+	// Generate some tokens from the test roles
+	req.Path = "auth/token/create/test-limited-uses"
+
+	// first token, num_uses is expected to come from the limited uses role
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
+	noOverrideToken := resp.Auth.ClientToken
+
+	// second token, override num_uses with a lesser value, this should become the value
+	// applied to the token
+	req.Data = map[string]interface{}{
+		"num_uses": lesserNumUses,
+	}
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
+	lesserOverrideToken := resp.Auth.ClientToken
+
+	// third token, override num_uses with a greater value, the value
+	// applied to the token should come from the limited uses role
+	req.Data = map[string]interface{}{
+		"num_uses": greaterNumUses,
+	}
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
+	greaterOverrideToken := resp.Auth.ClientToken
+
+	// fourth token, override num_uses with a zero value, a num_uses value of zero
+	// has an internal meaning of unlimited so num_uses == 1 is actually less than
+	// num_uses == 0. In this case, the lesser value of the limited-uses role should be applied.
+	req.Data = map[string]interface{}{
+		"num_uses": 0,
+	}
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
+	zeroOverrideToken := resp.Auth.ClientToken
+
+	// fifth token, override num_uses with a value from a role that has unlimited num_uses. num_uses
+	// should be the specified num_uses parameter at the create endpoint
+	req.Path = "auth/token/create/test-unlimited-uses"
+	req.Data = map[string]interface{}{
+		"num_uses": lesserNumUses,
+	}
+	resp, err = core.HandleRequest(namespace.RootContext(nil), req)
+	testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
+	unlimitedRoleOverrideToken := resp.Auth.ClientToken
+
+	testTokenStore_NumUses_SelfLookupHelper(t, core, noOverrideToken, roleNumUses)
+	testTokenStore_NumUses_SelfLookupHelper(t, core, lesserOverrideToken, lesserNumUses)
+	testTokenStore_NumUses_SelfLookupHelper(t, core, greaterOverrideToken, roleNumUses)
+	testTokenStore_NumUses_SelfLookupHelper(t, core, zeroOverrideToken, roleNumUses)
+	testTokenStore_NumUses_SelfLookupHelper(t, core, unlimitedRoleOverrideToken, lesserNumUses)
+}
+
 func TestTokenStore_Periodic_ExplicitMax(t *testing.T) {
 	core, _, root := TestCoreUnsealed(t)
 

From f257a8787381e2962d760be9640194e1a4a8bfc3 Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Thu, 13 Jun 2019 13:26:55 -0400
Subject: [PATCH 10/12] Rename to tokenutil

---
 .../{tokenhelper/tokenhelper.go => tokenutil/tokenutil.go}  | 2 +-
 vault/token_store.go                                        | 6 +++---
 vault/token_store_test.go                                   | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)
 rename sdk/helper/{tokenhelper/tokenhelper.go => tokenutil/tokenutil.go} (99%)

diff --git a/sdk/helper/tokenhelper/tokenhelper.go b/sdk/helper/tokenutil/tokenutil.go
similarity index 99%
rename from sdk/helper/tokenhelper/tokenhelper.go
rename to sdk/helper/tokenutil/tokenutil.go
index 3edb6ff7ca6e..6cf120b49c7b 100644
--- a/sdk/helper/tokenhelper/tokenhelper.go
+++ b/sdk/helper/tokenutil/tokenutil.go
@@ -1,4 +1,4 @@
-package tokenhelper
+package tokenutil
 
 import (
 	"errors"
diff --git a/vault/token_store.go b/vault/token_store.go
index d9907d179de7..1d2370731616 100644
--- a/vault/token_store.go
+++ b/vault/token_store.go
@@ -32,7 +32,7 @@ import (
 	"github.com/hashicorp/vault/sdk/helper/policyutil"
 	"github.com/hashicorp/vault/sdk/helper/salt"
 	"github.com/hashicorp/vault/sdk/helper/strutil"
-	"github.com/hashicorp/vault/sdk/helper/tokenhelper"
+	"github.com/hashicorp/vault/sdk/helper/tokenutil"
 	"github.com/hashicorp/vault/sdk/logical"
 	"github.com/hashicorp/vault/sdk/plugin/pb"
 	"github.com/mitchellh/mapstructure"
@@ -409,7 +409,7 @@ func (ts *TokenStore) paths() []*framework.Path {
 		ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
 	}
 
-	tokenhelper.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy", "token_num_uses"})
+	tokenutil.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy", "token_num_uses"})
 	p = append(p, rolesPath)
 
 	return p
@@ -579,7 +579,7 @@ func (ts *TokenStore) Salt(ctx context.Context) (*salt.Salt, error) {
 
 // tsRoleEntry contains token store role information
 type tsRoleEntry struct {
-	tokenhelper.TokenParams
+	tokenutil.TokenParams
 
 	// The name of the role. Embedded so it can be used for pathing
 	Name string `json:"name" mapstructure:"name" structs:"name"`
diff --git a/vault/token_store_test.go b/vault/token_store_test.go
index fd83411245df..0fabc3a157f1 100644
--- a/vault/token_store_test.go
+++ b/vault/token_store_test.go
@@ -22,7 +22,7 @@ import (
 	"github.com/hashicorp/vault/helper/namespace"
 	"github.com/hashicorp/vault/sdk/helper/locksutil"
 	"github.com/hashicorp/vault/sdk/helper/parseutil"
-	"github.com/hashicorp/vault/sdk/helper/tokenhelper"
+	"github.com/hashicorp/vault/sdk/helper/tokenutil"
 	"github.com/hashicorp/vault/sdk/logical"
 )
 
@@ -3628,7 +3628,7 @@ func TestTokenStore_RoleTokenFields(t *testing.T) {
 	{
 		roleEntry := &tsRoleEntry{
 			Name: "test",
-			TokenParams: tokenhelper.TokenParams{
+			TokenParams: tokenutil.TokenParams{
 				TokenType: logical.TokenTypeBatch,
 			},
 			Period:         time.Second,
@@ -3650,7 +3650,7 @@ func TestTokenStore_RoleTokenFields(t *testing.T) {
 		}
 		expRoleEntry := &tsRoleEntry{
 			Name: "test",
-			TokenParams: tokenhelper.TokenParams{
+			TokenParams: tokenutil.TokenParams{
 				TokenPeriod:         time.Second,
 				TokenExplicitMaxTTL: time.Hour,
 				TokenBoundCIDRs:     boundCIDRs,

From e826f0f3ce2239ae2f8e7693c46c24bc828ebaba Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Thu, 13 Jun 2019 13:31:22 -0400
Subject: [PATCH 11/12] Add comments

---
 sdk/helper/tokenutil/tokenutil.go | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sdk/helper/tokenutil/tokenutil.go b/sdk/helper/tokenutil/tokenutil.go
index 6cf120b49c7b..5945fd47e06b 100644
--- a/sdk/helper/tokenutil/tokenutil.go
+++ b/sdk/helper/tokenutil/tokenutil.go
@@ -12,6 +12,8 @@ import (
 	"github.com/hashicorp/vault/sdk/logical"
 )
 
+// TokenParams contains a set of common parameters that auth plugins can use
+// for setting token behavior
 type TokenParams struct {
 	// The set of CIDRs that tokens generated using this role will be bound to
 	TokenBoundCIDRs []*sockaddr.SockAddrMarshaler `json:"token_bound_cidrs"`
@@ -26,6 +28,9 @@ type TokenParams struct {
 	// If set, core will not automatically add default to the policy list
 	TokenNoDefaultPolicy bool `json:"token_no_default_policy" mapstructure:"token_no_default_policy"`
 
+	// The maximum number of times a token issued from this role may be used.
+	TokenNumUses int `json:"token_num_uses" mapstructure:"token_num_uses"`
+
 	// If non-zero, tokens created using this role will be able to be renewed
 	// forever, but will have a fixed renewal period of this value
 	TokenPeriod time.Duration `json:"token_period" mapstructure:"token_period"`
@@ -38,9 +43,6 @@ type TokenParams struct {
 
 	// The TTL to user for the token
 	TokenTTL time.Duration `json:"token_ttl" mapstructure:"token_ttl"`
-
-	// The maximum number of times a token issued from this role may be used.
-	TokenNumUses int `json:"token_num_uses" mapstructure:"token_num_uses"`
 }
 
 // AddTokenFields adds fields to an existing role. It panics if it would
@@ -49,6 +51,9 @@ func AddTokenFields(m map[string]*framework.FieldSchema) {
 	AddTokenFieldsWithAllowList(m, nil)
 }
 
+// AddTokenFields adds fields to an existing role. It panics if it would
+// overwrite an existing field. Allowed can be use to restrict the set, e.g. if
+// there would be conflicts.
 func AddTokenFieldsWithAllowList(m map[string]*framework.FieldSchema, allowed []string) {
 	r := TokenFields()
 	for k, v := range r {
@@ -62,6 +67,7 @@ func AddTokenFieldsWithAllowList(m map[string]*framework.FieldSchema, allowed []
 	}
 }
 
+// TokenFields provides a set of field schemas for the parameters
 func TokenFields() map[string]*framework.FieldSchema {
 	return map[string]*framework.FieldSchema{
 		"token_bound_cidrs": &framework.FieldSchema{
@@ -112,6 +118,7 @@ func TokenFields() map[string]*framework.FieldSchema {
 	}
 }
 
+// ParseTokenFields provides common field parsing functionality into a TokenFields struct
 func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldData) error {
 	if boundCIDRsRaw, ok := d.GetOk("token_bound_cidrs"); ok {
 		boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
@@ -185,6 +192,7 @@ func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldD
 	return nil
 }
 
+// PopulateTokenData adds information from TokenParams into the map
 func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
 	m["token_bound_cidrs"] = t.TokenBoundCIDRs
 	m["token_explicit_max_ttl"] = t.TokenExplicitMaxTTL.Seconds()
@@ -197,6 +205,7 @@ func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
 	m["token_num_uses"] = t.TokenNumUses
 }
 
+// PopulateTokenAuth populates Auth with parameters
 func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
 	auth.BoundCIDRs = t.TokenBoundCIDRs
 	auth.ExplicitMaxTTL = t.TokenExplicitMaxTTL

From 8c0009cd38ec26e924a30b3d28e43be8598ca8ca Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <jeffrey.mitchell@gmail.com>
Date: Thu, 13 Jun 2019 16:18:12 -0400
Subject: [PATCH 12/12] go mod tidy

---
 sdk/go.sum | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sdk/go.sum b/sdk/go.sum
index 5be807c7e084..2238d1fea1ac 100644
--- a/sdk/go.sum
+++ b/sdk/go.sum
@@ -52,7 +52,6 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/vault v1.1.2 h1:NDaWEwrTwjg3VKrKQmQykuiq4UqMUlbqloRvIX5fhns=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=