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:
parent
ec8e05c52c
commit
db9d9e6415
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"])
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue