Store original request path in WrapInfo (#3100)

* Store original request path in WrapInfo as CreationPath

* Add wrapping_token_creation_path to CLI output

* Add CreationPath to AuditResponseWrapInfo

* Fix tests

* Add and fix tests, update API docs with new sample responses
This commit is contained in:
Calvin Leung Huang 2017-08-02 18:28:58 -04:00 committed by GitHub
parent ec8e05c52c
commit db9d9e6415
15 changed files with 70 additions and 11 deletions

View File

@ -42,6 +42,7 @@ type SecretWrapInfo struct {
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime time.Time `json:"creation_time"`
CreationPath string `json:"creation_path"`
WrappedAccessor string `json:"wrapped_accessor"`
}

View File

@ -300,6 +300,7 @@ func (f *AuditFormatter) FormatResponse(
TTL: int(resp.WrapInfo.TTL / time.Second),
Token: token,
CreationTime: resp.WrapInfo.CreationTime.Format(time.RFC3339Nano),
CreationPath: resp.WrapInfo.CreationPath,
WrappedAccessor: resp.WrapInfo.WrappedAccessor,
}
}
@ -406,6 +407,7 @@ type AuditResponseWrapInfo struct {
TTL int `json:"ttl"`
Token string `json:"token"`
CreationTime string `json:"creation_time"`
CreationPath string `json:"creation_path"`
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
}

View File

@ -181,6 +181,7 @@ func (t TableFormatter) OutputSecret(ui cli.Ui, secret, s *api.Secret) error {
input = append(input, fmt.Sprintf("wrapping_token: %s %s", config.Delim, s.WrapInfo.Token))
input = append(input, fmt.Sprintf("wrapping_token_ttl: %s %s", config.Delim, (time.Second*time.Duration(s.WrapInfo.TTL)).String()))
input = append(input, fmt.Sprintf("wrapping_token_creation_time: %s %s", config.Delim, s.WrapInfo.CreationTime.String()))
input = append(input, fmt.Sprintf("wrapping_token_creation_path: %s %s", config.Delim, s.WrapInfo.CreationPath))
if s.WrapInfo.WrappedAccessor != "" {
input = append(input, fmt.Sprintf("wrapped_accessor: %s %s", config.Delim, s.WrapInfo.WrappedAccessor))
}

View File

@ -57,6 +57,8 @@ func PrintRawField(ui cli.Ui, secret *api.Secret, field string) int {
val = secret.WrapInfo.TTL
case "wrapping_token_creation_time":
val = secret.WrapInfo.CreationTime.Format(time.RFC3339Nano)
case "wrapping_token_creation_path":
val = secret.WrapInfo.CreationPath
case "wrapped_accessor":
val = secret.WrapInfo.WrappedAccessor
default:

View File

@ -12,7 +12,7 @@ type ResponseWrapInfo struct {
// The creation time. This can be used with the TTL to figure out an
// expected expiration.
CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"cration_time"`
CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"creation_time"`
// If the contained response is the output of a token creation call, the
// created token's accessor will be accessible here
@ -20,4 +20,8 @@ type ResponseWrapInfo struct {
// The format to use. This doesn't get returned, it's only internal.
Format string `json:"format" structs:"format" mapstructure:"format"`
// CreationPath is the original request path that was used to create
// the wrapped response.
CreationPath string `json:"creation_path" structs:"creation_path" mapstructure:"creation_path"`
}

View File

@ -282,6 +282,12 @@ func TestSysMounts_headerAuth_Wrapped(t *testing.T) {
}
expected["wrap_info"].(map[string]interface{})["creation_time"] = actualCreationTime
actualCreationPath, ok := actual["wrap_info"].(map[string]interface{})["creation_path"]
if !ok || actualCreationPath == "" {
t.Fatal("creation_path missing in wrap info")
}
expected["wrap_info"].(map[string]interface{})["creation_path"] = actualCreationPath
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad:\nExpected: %#v\nActual: %#v\n%T %T", expected, actual, actual["warnings"], actual["data"])
}

View File

@ -153,6 +153,7 @@ func respondLogical(w http.ResponseWriter, r *http.Request, req *logical.Request
Token: resp.WrapInfo.Token,
TTL: int(resp.WrapInfo.TTL.Seconds()),
CreationTime: resp.WrapInfo.CreationTime.Format(time.RFC3339Nano),
CreationPath: resp.WrapInfo.CreationPath,
WrappedAccessor: resp.WrapInfo.WrappedAccessor,
},
}

View File

@ -308,6 +308,11 @@ func TestHTTP_Wrapping(t *testing.T) {
}
wrapInfo = secret.WrapInfo
// Check for correct CreationPath before rewrap
if wrapInfo.CreationPath != "secret/foo" {
t.Fatal("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
}
// Test rewrapping
secret, err = client.Logical().Write("sys/wrapping/rewrap", map[string]interface{}{
"token": wrapInfo.Token,
@ -315,6 +320,12 @@ func TestHTTP_Wrapping(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// Check for correct Creation path after rewrap
if wrapInfo.CreationPath != "secret/foo" {
t.Fatal("error on wrapInfo.CreationPath: expected: secret/foo, got: %s", wrapInfo.CreationPath)
}
// Should be expired and fail
_, err = client.Logical().Write("sys/wrapping/unwrap", map[string]interface{}{
"token": wrapInfo.Token,

View File

@ -91,6 +91,7 @@ type HTTPWrapInfo struct {
Token string `json:"token"`
TTL int `json:"ttl"`
CreationTime string `json:"creation_time"`
CreationPath string `json:"creation_path"`
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
}

View File

@ -2204,6 +2204,7 @@ func (b *SystemBackend) handleWrappingLookup(
creationTTLRaw := cubbyResp.Data["creation_ttl"]
creationTime := cubbyResp.Data["creation_time"]
creationPath := cubbyResp.Data["creation_path"]
resp := &logical.Response{
Data: map[string]interface{}{},
@ -2219,6 +2220,9 @@ func (b *SystemBackend) handleWrappingLookup(
// This was JSON marshaled so it's already a string in RFC3339 format
resp.Data["creation_time"] = cubbyResp.Data["creation_time"]
}
if creationPath != nil {
resp.Data["creation_path"] = cubbyResp.Data["creation_path"]
}
return resp, nil
}
@ -2278,6 +2282,13 @@ func (b *SystemBackend) handleWrappingRewrap(
return nil, fmt.Errorf("error reading creation_ttl value from wrapping information: %v", err)
}
// Get creation_path to return as the response later
creationPathRaw := cubbyResp.Data["creation_path"]
if creationPathRaw == nil {
return nil, fmt.Errorf("creation_path value in wrapping information was nil")
}
creationPath := creationPathRaw.(string)
// Fetch the original response and return it as the data for the new response
cubbyReq = &logical.Request{
Operation: logical.ReadOperation,
@ -2310,7 +2321,8 @@ func (b *SystemBackend) handleWrappingRewrap(
"response": response,
},
WrapInfo: &wrapping.ResponseWrapInfo{
TTL: time.Duration(creationTTL),
TTL: time.Duration(creationTTL),
CreationPath: creationPath,
},
}, nil
}

View File

@ -189,7 +189,7 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
if resp != nil {
// If wrapping is used, use the shortest between the request and response
var wrapTTL time.Duration
var wrapFormat string
var wrapFormat, creationPath string
// Ensure no wrap info information is set other than, possibly, the TTL
if resp.WrapInfo != nil {
@ -197,6 +197,7 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
wrapTTL = resp.WrapInfo.TTL
}
wrapFormat = resp.WrapInfo.Format
creationPath = resp.WrapInfo.CreationPath
resp.WrapInfo = nil
}
@ -218,8 +219,9 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
if wrapTTL > 0 {
resp.WrapInfo = &wrapping.ResponseWrapInfo{
TTL: wrapTTL,
Format: wrapFormat,
TTL: wrapTTL,
Format: wrapFormat,
CreationPath: creationPath,
}
}
}
@ -338,7 +340,7 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, *log
if resp != nil {
// If wrapping is used, use the shortest between the request and response
var wrapTTL time.Duration
var wrapFormat string
var wrapFormat, creationPath string
// Ensure no wrap info information is set other than, possibly, the TTL
if resp.WrapInfo != nil {
@ -346,6 +348,7 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, *log
wrapTTL = resp.WrapInfo.TTL
}
wrapFormat = resp.WrapInfo.Format
creationPath = resp.WrapInfo.CreationPath
resp.WrapInfo = nil
}
@ -365,8 +368,9 @@ func (c *Core) handleLoginRequest(req *logical.Request) (*logical.Response, *log
if wrapTTL > 0 {
resp.WrapInfo = &wrapping.ResponseWrapInfo{
TTL: wrapTTL,
Format: wrapFormat,
TTL: wrapTTL,
Format: wrapFormat,
CreationPath: creationPath,
}
}
}

View File

@ -115,6 +115,10 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response) (*l
resp.WrapInfo.Token = te.ID
resp.WrapInfo.CreationTime = creationTime
// If this is not a rewrap, store the request path as creation_path
if req.Path != "sys/wrapping/rewrap" {
resp.WrapInfo.CreationPath = req.Path
}
// This will only be non-nil if this response contains a token, so in that
// case put the accessor in the wrap info.
@ -200,6 +204,12 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response) (*l
"creation_ttl": resp.WrapInfo.TTL,
"creation_time": creationTime,
}
// Store creation_path if not a rewrap
if req.Path != "sys/wrapping/rewrap" {
cubbyReq.Data["creation_path"] = req.Path
} else {
cubbyReq.Data["creation_path"] = resp.WrapInfo.CreationPath
}
cubbyResp, err = c.router.Route(cubbyReq)
if err != nil {
// Revoke since it's not yet being tracked for expiration
@ -233,6 +243,7 @@ func (c *Core) wrapInCubbyhole(req *logical.Request, resp *logical.Response) (*l
return nil, nil
}
// ValidateWrappingToken checks whether a token is a wrapping token.
func (c *Core) ValidateWrappingToken(req *logical.Request) (bool, error) {
if req == nil {
return false, fmt.Errorf("invalid request")

View File

@ -49,9 +49,12 @@ $ curl \
"lease_duration": 0,
"renewable": false,
"data": {
"creation_path": "sys/wrapping/wrap",
"creation_time": "2016-09-28T14:16:13.07103516-04:00",
"creation_ttl": 300
},
"warnings": null
"wrap_info": null,
"warnings": null,
"auth": null
}
```

View File

@ -58,7 +58,7 @@ $ curl \
"token": "3b6f1193-0707-ac17-284d-e41032e74d1f",
"ttl": 300,
"creation_time": "2016-09-28T14:22:26.486186607-04:00",
"wrapped_accessor": ""
"creation_path": "sys/wrapping/wrap"
}
}
```

View File

@ -61,7 +61,7 @@ $ curl \
"token": "fb79b9d3-d94e-9eb6-4919-c559311133d6",
"ttl": 300,
"creation_time": "2016-09-28T14:41:00.56961496-04:00",
"wrapped_accessor": ""
"creation_path": "sys/wrapping/wrap",
}
}
```