Add no-default-policy flag and API parameter to allow exclusion of the

default policy from a token create command.
This commit is contained in:
Jeff Mitchell 2015-11-09 17:30:50 -05:00
parent d6693129de
commit 1a45696208
7 changed files with 81 additions and 27 deletions

View File

@ -25,7 +25,9 @@ FEATURES:
which allows a token to retrieve its own information, and `revoke-self` and which allows a token to retrieve its own information, and `revoke-self` and
`renew-self`, which are self-explanatory. If your existing Vault `renew-self`, which are self-explanatory. If your existing Vault
installation contains a policy called `default`, it will not be overridden, installation contains a policy called `default`, it will not be overridden,
but it will be added to each new token created. [GH-732] but it will be added to each new token created. You can override this
behavior when using manual token creation (i.e. not via an authentication
backend) by setting the "no_default_policy" flag to true. [GH-732]
IMPROVEMENTS: IMPROVEMENTS:

View File

@ -117,12 +117,13 @@ func (c *TokenAuth) RevokeTree(token string) error {
// TokenCreateRequest is the options structure for creating a token. // TokenCreateRequest is the options structure for creating a token.
type TokenCreateRequest struct { type TokenCreateRequest struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Policies []string `json:"policies,omitempty"` Policies []string `json:"policies,omitempty"`
Metadata map[string]string `json:"meta,omitempty"` Metadata map[string]string `json:"meta,omitempty"`
Lease string `json:"lease,omitempty"` Lease string `json:"lease,omitempty"`
TTL string `json:"ttl,omitempty"` TTL string `json:"ttl,omitempty"`
NoParent bool `json:"no_parent,omitempty"` NoParent bool `json:"no_parent,omitempty"`
DisplayName string `json:"display_name"` NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
NumUses int `json:"num_uses"` DisplayName string `json:"display_name"`
NumUses int `json:"num_uses"`
} }

View File

@ -17,7 +17,7 @@ type TokenCreateCommand struct {
func (c *TokenCreateCommand) Run(args []string) int { func (c *TokenCreateCommand) Run(args []string) int {
var format string var format string
var id, displayName, lease, ttl string var id, displayName, lease, ttl string
var orphan bool var orphan, noDefaultPolicy bool
var metadata map[string]string var metadata map[string]string
var numUses int var numUses int
var policies []string var policies []string
@ -28,6 +28,7 @@ func (c *TokenCreateCommand) Run(args []string) int {
flags.StringVar(&lease, "lease", "", "") flags.StringVar(&lease, "lease", "", "")
flags.StringVar(&ttl, "ttl", "", "") flags.StringVar(&ttl, "ttl", "", "")
flags.BoolVar(&orphan, "orphan", false, "") flags.BoolVar(&orphan, "orphan", false, "")
flags.BoolVar(&noDefaultPolicy, "no-default-policy", false, "")
flags.IntVar(&numUses, "use-limit", 0, "") flags.IntVar(&numUses, "use-limit", 0, "")
flags.Var((*kvFlag.Flag)(&metadata), "metadata", "") flags.Var((*kvFlag.Flag)(&metadata), "metadata", "")
flags.Var((*sliceflag.StringFlag)(&policies), "policy", "") flags.Var((*sliceflag.StringFlag)(&policies), "policy", "")
@ -55,13 +56,14 @@ func (c *TokenCreateCommand) Run(args []string) int {
ttl = lease ttl = lease
} }
secret, err := client.Auth().Token().Create(&api.TokenCreateRequest{ secret, err := client.Auth().Token().Create(&api.TokenCreateRequest{
ID: id, ID: id,
Policies: policies, Policies: policies,
Metadata: metadata, Metadata: metadata,
TTL: ttl, TTL: ttl,
NoParent: orphan, NoParent: orphan,
DisplayName: displayName, NoDefaultPolicy: noDefaultPolicy,
NumUses: numUses, DisplayName: displayName,
NumUses: numUses,
}) })
if err != nil { if err != nil {
@ -122,6 +124,9 @@ Token Options:
root tokens can create orphan tokens. This prevents root tokens can create orphan tokens. This prevents
the new token from being revoked with your token. the new token from being revoked with your token.
-no-default-policy If specified, the token will not have the "default"
policy included in its policy set.
-policy="name" Policy to associate with this token. This can be -policy="name" Policy to associate with this token. This can be
specified multiple times. specified multiple times.

View File

@ -1036,6 +1036,45 @@ func TestCore_HandleRequest_CreateToken_Lease(t *testing.T) {
} }
} }
// Check that we handle excluding the default policy
func TestCore_HandleRequest_CreateToken_NoDefaultPolicy(t *testing.T) {
c, _, root := TestCoreUnsealed(t)
// Create a new credential
req := logical.TestRequest(t, logical.WriteOperation, "auth/token/create")
req.ClientToken = root
req.Data["policies"] = []string{"foo"}
req.Data["no_default_policy"] = true
resp, err := c.HandleRequest(req)
if err != nil {
t.Fatalf("err: %v", err)
}
// Ensure we got a new client token back
clientToken := resp.Auth.ClientToken
if clientToken == "" {
t.Fatalf("bad: %#v", resp)
}
// Check the policy and metadata
te, err := c.tokenStore.Lookup(clientToken)
if err != nil {
t.Fatalf("err: %v", err)
}
expect := &TokenEntry{
ID: clientToken,
Parent: root,
Policies: []string{"foo"},
Path: "auth/token/create",
DisplayName: "token",
CreationTime: te.CreationTime,
TTL: time.Hour * 24 * 30,
}
if !reflect.DeepEqual(te, expect) {
t.Fatalf("Bad: %#v expect: %#v", te, expect)
}
}
func TestCore_LimitedUseToken(t *testing.T) { func TestCore_LimitedUseToken(t *testing.T) {
c, _, root := TestCoreUnsealed(t) c, _, root := TestCoreUnsealed(t)

View File

@ -547,14 +547,15 @@ func (ts *TokenStore) handleCreateCommon(
// Read and parse the fields // Read and parse the fields
var data struct { var data struct {
ID string ID string
Policies []string Policies []string
Metadata map[string]string `mapstructure:"meta"` Metadata map[string]string `mapstructure:"meta"`
NoParent bool `mapstructure:"no_parent"` NoParent bool `mapstructure:"no_parent"`
Lease string NoDefaultPolicy bool `mapstructure:"no_default_policy"`
TTL string Lease string
DisplayName string `mapstructure:"display_name"` TTL string
NumUses int `mapstructure:"num_uses"` DisplayName string `mapstructure:"display_name"`
NumUses int `mapstructure:"num_uses"`
} }
if err := mapstructure.WeakDecode(req.Data, &data); err != nil { if err := mapstructure.WeakDecode(req.Data, &data); err != nil {
return logical.ErrorResponse(fmt.Sprintf( return logical.ErrorResponse(fmt.Sprintf(
@ -602,7 +603,7 @@ func (ts *TokenStore) handleCreateCommon(
return logical.ErrorResponse("child policies must be subset of parent"), logical.ErrInvalidRequest return logical.ErrorResponse("child policies must be subset of parent"), logical.ErrInvalidRequest
} }
te.Policies = data.Policies te.Policies = data.Policies
if !strListSubset(te.Policies, []string{"root"}) { if !strListSubset(te.Policies, []string{"root"}) && !data.NoDefaultPolicy {
te.Policies = append(te.Policies, "default") te.Policies = append(te.Policies, "default")
} }

View File

@ -888,7 +888,7 @@ func TestTokenStore_HandleRequest_Lookup(t *testing.T) {
exp = map[string]interface{}{ exp = map[string]interface{}{
"id": "client", "id": "client",
"policies": []string{"foo"}, "policies": []string{"foo", "default"},
"path": "auth/token/create", "path": "auth/token/create",
"meta": map[string]string(nil), "meta": map[string]string(nil),
"display_name": "token", "display_name": "token",

View File

@ -87,6 +87,12 @@ of the header should be "X-Vault-Token" and the value should be the token.
If true and set by a root caller, the token will not have the If true and set by a root caller, the token will not have the
parent token of the caller. This creates a token with no parent. parent token of the caller. This creates a token with no parent.
</li> </li>
<li>
<span class="param">no_default_profile</span>
<span class="param-flags">optional</span>
If true the `default` profile will not be a part of this token's
policy set.
</li>
<li> <li>
<span class="param">lease</span> <span class="param">lease</span>
<span class="param-flags">optional</span> <span class="param-flags">optional</span>