1
0

Add allowed_response_headers (#6115)

This commit is contained in:
Jeff Mitchell 2019-02-05 16:02:15 -05:00 committed by GitHub
parent 69d3fdd2b8
commit 20423f7082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 728 additions and 423 deletions

View File

@ -151,6 +151,7 @@ type MountConfigInput struct {
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
TokenType string `json:"token_type,omitempty" mapstructure:"token_type"`
// Deprecated: This field will always be blank for newer server responses.
@ -175,6 +176,7 @@ type MountConfigOutput struct {
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
TokenType string `json:"token_type,omitempty" mapstructure:"token_type"`
// Deprecated: This field will always be blank for newer server responses.

View File

@ -373,6 +373,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
Data: resp.Data,
Redirect: resp.Redirect,
WrapInfo: respWrapInfo,
Headers: resp.Headers,
},
}
@ -427,6 +428,7 @@ type AuditResponse struct {
Data map[string]interface{} `json:"data,omitempty"`
Redirect string `json:"redirect,omitempty"`
WrapInfo *AuditResponseWrapInfo `json:"wrap_info,omitempty"`
Headers map[string][]string `json:"headers"`
}
type AuditAuth struct {

View File

@ -5,15 +5,11 @@ package dbplugin
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
)
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -679,6 +675,60 @@ func init() {
proto.RegisterType((*Empty)(nil), "dbplugin.Empty")
}
func init() {
proto.RegisterFile("builtin/logical/database/dbplugin/database.proto", fileDescriptor_7bf7b4c7fef2f66e)
}
var fileDescriptor_7bf7b4c7fef2f66e = []byte{
// 724 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xd1, 0x4e, 0xdb, 0x4a,
0x10, 0x95, 0x93, 0x00, 0xc9, 0x80, 0x80, 0xec, 0x05, 0x64, 0xf9, 0x72, 0x6f, 0x91, 0x1f, 0x28,
0x55, 0xd5, 0xb8, 0x82, 0x56, 0x54, 0xa8, 0xa2, 0x2a, 0xa1, 0xaa, 0x2a, 0x55, 0x3c, 0x2c, 0xf0,
0x52, 0x55, 0x42, 0x1b, 0x67, 0x49, 0x56, 0x38, 0x5e, 0xd7, 0xbb, 0x0e, 0x4d, 0x7f, 0xa0, 0xfd,
0x8c, 0x7e, 0x4e, 0x1f, 0xfb, 0x49, 0x95, 0x37, 0x59, 0xef, 0x26, 0x86, 0xf2, 0x40, 0xfb, 0xe6,
0xd9, 0x99, 0x33, 0x73, 0xe6, 0x78, 0x76, 0x16, 0x9e, 0x76, 0x32, 0x16, 0x49, 0x16, 0x07, 0x11,
0xef, 0xb1, 0x90, 0x44, 0x41, 0x97, 0x48, 0xd2, 0x21, 0x82, 0x06, 0xdd, 0x4e, 0x12, 0x65, 0x3d,
0x16, 0x17, 0x27, 0xad, 0x24, 0xe5, 0x92, 0xa3, 0xba, 0x76, 0x78, 0x0f, 0x7a, 0x9c, 0xf7, 0x22,
0x1a, 0xa8, 0xf3, 0x4e, 0x76, 0x19, 0x48, 0x36, 0xa0, 0x42, 0x92, 0x41, 0x32, 0x0e, 0xf5, 0x3f,
0x42, 0xf3, 0x5d, 0xcc, 0x24, 0x23, 0x11, 0xfb, 0x42, 0x31, 0xfd, 0x94, 0x51, 0x21, 0xd1, 0x06,
0xcc, 0x87, 0x3c, 0xbe, 0x64, 0x3d, 0xd7, 0xd9, 0x72, 0x76, 0x96, 0xf0, 0xc4, 0x42, 0x8f, 0xa1,
0x39, 0xa4, 0x29, 0xbb, 0x1c, 0x5d, 0x84, 0x3c, 0x8e, 0x69, 0x28, 0x19, 0x8f, 0xdd, 0xca, 0x96,
0xb3, 0x53, 0xc7, 0xab, 0x63, 0x47, 0xbb, 0x38, 0x3f, 0xa8, 0xb8, 0x8e, 0x8f, 0x61, 0x31, 0xcf,
0xfe, 0x27, 0xf3, 0xfa, 0x3f, 0x1c, 0x68, 0xb6, 0x53, 0x4a, 0x24, 0x3d, 0x17, 0x34, 0xd5, 0xa9,
0x9f, 0x01, 0x08, 0x49, 0x24, 0x1d, 0xd0, 0x58, 0x0a, 0x95, 0x7e, 0x71, 0x77, 0xad, 0xa5, 0x75,
0x68, 0x9d, 0x16, 0x3e, 0x6c, 0xc5, 0xa1, 0xd7, 0xb0, 0x92, 0x09, 0x9a, 0xc6, 0x64, 0x40, 0x2f,
0x26, 0xcc, 0x2a, 0x0a, 0xea, 0x1a, 0xe8, 0xf9, 0x24, 0xa0, 0xad, 0xfc, 0x78, 0x39, 0x9b, 0xb2,
0xd1, 0x01, 0x00, 0xfd, 0x9c, 0xb0, 0x94, 0x28, 0xd2, 0x55, 0x85, 0xf6, 0x5a, 0x63, 0xd9, 0x5b,
0x5a, 0xf6, 0xd6, 0x99, 0x96, 0x1d, 0x5b, 0xd1, 0xfe, 0x77, 0x07, 0x56, 0x31, 0x8d, 0xe9, 0xf5,
0xfd, 0x3b, 0xf1, 0xa0, 0xae, 0x89, 0xa9, 0x16, 0x1a, 0xb8, 0xb0, 0xef, 0x45, 0x91, 0x42, 0x13,
0xd3, 0x21, 0xbf, 0xa2, 0x7f, 0x95, 0xa2, 0x7f, 0x08, 0x9b, 0x98, 0xe7, 0xa1, 0x98, 0x73, 0xd9,
0x4e, 0x69, 0x97, 0xc6, 0xf9, 0x4c, 0x0a, 0x5d, 0xf1, 0xff, 0x99, 0x8a, 0xd5, 0x9d, 0x86, 0x9d,
0xdb, 0xff, 0x59, 0x01, 0x30, 0x65, 0xd1, 0x1e, 0xfc, 0x13, 0xe6, 0x23, 0xc2, 0x78, 0x7c, 0x31,
0xc3, 0xb4, 0x71, 0x54, 0x71, 0x1d, 0x8c, 0xb4, 0xdb, 0x02, 0xed, 0xc3, 0x7a, 0x4a, 0x87, 0x3c,
0x2c, 0xc1, 0x2a, 0x05, 0x6c, 0xcd, 0x04, 0x4c, 0x57, 0x4b, 0x79, 0x14, 0x75, 0x48, 0x78, 0x65,
0xc3, 0xaa, 0xa6, 0x9a, 0x76, 0x5b, 0xa0, 0x27, 0xb0, 0x9a, 0xe6, 0xbf, 0xde, 0x46, 0xd4, 0x0a,
0xc4, 0x8a, 0xf2, 0x9d, 0x4e, 0x89, 0xa7, 0x29, 0xbb, 0x73, 0xaa, 0xfd, 0xc2, 0xce, 0xc5, 0x31,
0xbc, 0xdc, 0xf9, 0xb1, 0x38, 0xe6, 0x24, 0xc7, 0x6a, 0x02, 0xee, 0xc2, 0x18, 0xab, 0x6d, 0xe4,
0xc2, 0x82, 0x2a, 0x45, 0x22, 0xb7, 0xae, 0x5c, 0xda, 0xf4, 0x4f, 0x60, 0x79, 0x7a, 0xf4, 0xd1,
0x16, 0x2c, 0x1e, 0x33, 0x91, 0x44, 0x64, 0x74, 0x92, 0xff, 0x43, 0xa5, 0x26, 0xb6, 0x8f, 0xf2,
0x4a, 0x98, 0x47, 0xf4, 0xc4, 0xfa, 0xc5, 0xda, 0xf6, 0xb7, 0x61, 0x69, 0xbc, 0x0b, 0x44, 0xc2,
0x63, 0x41, 0x6f, 0x5b, 0x06, 0xfe, 0x7b, 0x40, 0xf6, 0xf5, 0x9e, 0x44, 0xdb, 0xc3, 0xe3, 0xcc,
0xcc, 0xb7, 0x07, 0xf5, 0x84, 0x08, 0x71, 0xcd, 0xd3, 0xae, 0xae, 0xaa, 0x6d, 0xdf, 0x87, 0xa5,
0xb3, 0x51, 0x42, 0x8b, 0x3c, 0x08, 0x6a, 0x72, 0x94, 0xe8, 0x1c, 0xea, 0xdb, 0xdf, 0x87, 0xff,
0x6e, 0x19, 0xbe, 0x3b, 0xa8, 0x2e, 0xc0, 0xdc, 0x9b, 0x41, 0x22, 0x47, 0xbb, 0x5f, 0x6b, 0x50,
0x3f, 0x9e, 0xec, 0x60, 0x14, 0x40, 0x2d, 0x2f, 0x89, 0x56, 0xcc, 0x8d, 0x50, 0x51, 0xde, 0x86,
0x39, 0x98, 0xe2, 0xf4, 0x16, 0xc0, 0x74, 0x8c, 0xfe, 0x35, 0x51, 0xa5, 0x35, 0xe7, 0x6d, 0xde,
0xec, 0x9c, 0x24, 0x7a, 0x01, 0x8d, 0x62, 0x9d, 0x20, 0xcf, 0x84, 0xce, 0xee, 0x18, 0x6f, 0x96,
0x5a, 0xbe, 0x22, 0xcc, 0x35, 0xb7, 0x29, 0x94, 0x2e, 0x7f, 0x19, 0xdb, 0x87, 0xf5, 0x1b, 0xe5,
0x43, 0xdb, 0x56, 0x9a, 0xdf, 0x5c, 0x6e, 0xef, 0xe1, 0x9d, 0x71, 0x93, 0xfe, 0x9e, 0x43, 0x2d,
0x1f, 0x21, 0xb4, 0x6e, 0x00, 0xd6, 0xf3, 0x62, 0xeb, 0x3b, 0x35, 0x69, 0x8f, 0x60, 0xae, 0x1d,
0x71, 0x71, 0xc3, 0x1f, 0x29, 0xf5, 0xf2, 0x0a, 0xc0, 0x3c, 0x87, 0xb6, 0x0e, 0xa5, 0x47, 0xb2,
0x84, 0xf5, 0xab, 0xdf, 0x2a, 0xce, 0xd1, 0xe1, 0x87, 0x97, 0x3d, 0x26, 0xfb, 0x59, 0xa7, 0x15,
0xf2, 0x41, 0xd0, 0x27, 0xa2, 0xcf, 0x42, 0x9e, 0x26, 0xc1, 0x90, 0x64, 0x91, 0x0c, 0xee, 0x7c,
0xc9, 0x3b, 0xf3, 0x6a, 0x1f, 0xef, 0xfd, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x9c, 0x49, 0x0b, 0x5b,
0xf5, 0x07, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
@ -982,57 +1032,3 @@ var _Database_serviceDesc = grpc.ServiceDesc{
Streams: []grpc.StreamDesc{},
Metadata: "builtin/logical/database/dbplugin/database.proto",
}
func init() {
proto.RegisterFile("builtin/logical/database/dbplugin/database.proto", fileDescriptor_7bf7b4c7fef2f66e)
}
var fileDescriptor_7bf7b4c7fef2f66e = []byte{
// 724 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xd1, 0x4e, 0xdb, 0x4a,
0x10, 0x95, 0x93, 0x00, 0xc9, 0x80, 0x80, 0xec, 0x05, 0x64, 0xf9, 0x72, 0x6f, 0x91, 0x1f, 0x28,
0x55, 0xd5, 0xb8, 0x82, 0x56, 0x54, 0xa8, 0xa2, 0x2a, 0xa1, 0xaa, 0x2a, 0x55, 0x3c, 0x2c, 0xf0,
0x52, 0x55, 0x42, 0x1b, 0x67, 0x49, 0x56, 0x38, 0x5e, 0xd7, 0xbb, 0x0e, 0x4d, 0x7f, 0xa0, 0xfd,
0x8c, 0x7e, 0x4e, 0x1f, 0xfb, 0x49, 0x95, 0x37, 0x59, 0xef, 0x26, 0x86, 0xf2, 0x40, 0xfb, 0xe6,
0xd9, 0x99, 0x33, 0x73, 0xe6, 0x78, 0x76, 0x16, 0x9e, 0x76, 0x32, 0x16, 0x49, 0x16, 0x07, 0x11,
0xef, 0xb1, 0x90, 0x44, 0x41, 0x97, 0x48, 0xd2, 0x21, 0x82, 0x06, 0xdd, 0x4e, 0x12, 0x65, 0x3d,
0x16, 0x17, 0x27, 0xad, 0x24, 0xe5, 0x92, 0xa3, 0xba, 0x76, 0x78, 0x0f, 0x7a, 0x9c, 0xf7, 0x22,
0x1a, 0xa8, 0xf3, 0x4e, 0x76, 0x19, 0x48, 0x36, 0xa0, 0x42, 0x92, 0x41, 0x32, 0x0e, 0xf5, 0x3f,
0x42, 0xf3, 0x5d, 0xcc, 0x24, 0x23, 0x11, 0xfb, 0x42, 0x31, 0xfd, 0x94, 0x51, 0x21, 0xd1, 0x06,
0xcc, 0x87, 0x3c, 0xbe, 0x64, 0x3d, 0xd7, 0xd9, 0x72, 0x76, 0x96, 0xf0, 0xc4, 0x42, 0x8f, 0xa1,
0x39, 0xa4, 0x29, 0xbb, 0x1c, 0x5d, 0x84, 0x3c, 0x8e, 0x69, 0x28, 0x19, 0x8f, 0xdd, 0xca, 0x96,
0xb3, 0x53, 0xc7, 0xab, 0x63, 0x47, 0xbb, 0x38, 0x3f, 0xa8, 0xb8, 0x8e, 0x8f, 0x61, 0x31, 0xcf,
0xfe, 0x27, 0xf3, 0xfa, 0x3f, 0x1c, 0x68, 0xb6, 0x53, 0x4a, 0x24, 0x3d, 0x17, 0x34, 0xd5, 0xa9,
0x9f, 0x01, 0x08, 0x49, 0x24, 0x1d, 0xd0, 0x58, 0x0a, 0x95, 0x7e, 0x71, 0x77, 0xad, 0xa5, 0x75,
0x68, 0x9d, 0x16, 0x3e, 0x6c, 0xc5, 0xa1, 0xd7, 0xb0, 0x92, 0x09, 0x9a, 0xc6, 0x64, 0x40, 0x2f,
0x26, 0xcc, 0x2a, 0x0a, 0xea, 0x1a, 0xe8, 0xf9, 0x24, 0xa0, 0xad, 0xfc, 0x78, 0x39, 0x9b, 0xb2,
0xd1, 0x01, 0x00, 0xfd, 0x9c, 0xb0, 0x94, 0x28, 0xd2, 0x55, 0x85, 0xf6, 0x5a, 0x63, 0xd9, 0x5b,
0x5a, 0xf6, 0xd6, 0x99, 0x96, 0x1d, 0x5b, 0xd1, 0xfe, 0x77, 0x07, 0x56, 0x31, 0x8d, 0xe9, 0xf5,
0xfd, 0x3b, 0xf1, 0xa0, 0xae, 0x89, 0xa9, 0x16, 0x1a, 0xb8, 0xb0, 0xef, 0x45, 0x91, 0x42, 0x13,
0xd3, 0x21, 0xbf, 0xa2, 0x7f, 0x95, 0xa2, 0x7f, 0x08, 0x9b, 0x98, 0xe7, 0xa1, 0x98, 0x73, 0xd9,
0x4e, 0x69, 0x97, 0xc6, 0xf9, 0x4c, 0x0a, 0x5d, 0xf1, 0xff, 0x99, 0x8a, 0xd5, 0x9d, 0x86, 0x9d,
0xdb, 0xff, 0x59, 0x01, 0x30, 0x65, 0xd1, 0x1e, 0xfc, 0x13, 0xe6, 0x23, 0xc2, 0x78, 0x7c, 0x31,
0xc3, 0xb4, 0x71, 0x54, 0x71, 0x1d, 0x8c, 0xb4, 0xdb, 0x02, 0xed, 0xc3, 0x7a, 0x4a, 0x87, 0x3c,
0x2c, 0xc1, 0x2a, 0x05, 0x6c, 0xcd, 0x04, 0x4c, 0x57, 0x4b, 0x79, 0x14, 0x75, 0x48, 0x78, 0x65,
0xc3, 0xaa, 0xa6, 0x9a, 0x76, 0x5b, 0xa0, 0x27, 0xb0, 0x9a, 0xe6, 0xbf, 0xde, 0x46, 0xd4, 0x0a,
0xc4, 0x8a, 0xf2, 0x9d, 0x4e, 0x89, 0xa7, 0x29, 0xbb, 0x73, 0xaa, 0xfd, 0xc2, 0xce, 0xc5, 0x31,
0xbc, 0xdc, 0xf9, 0xb1, 0x38, 0xe6, 0x24, 0xc7, 0x6a, 0x02, 0xee, 0xc2, 0x18, 0xab, 0x6d, 0xe4,
0xc2, 0x82, 0x2a, 0x45, 0x22, 0xb7, 0xae, 0x5c, 0xda, 0xf4, 0x4f, 0x60, 0x79, 0x7a, 0xf4, 0xd1,
0x16, 0x2c, 0x1e, 0x33, 0x91, 0x44, 0x64, 0x74, 0x92, 0xff, 0x43, 0xa5, 0x26, 0xb6, 0x8f, 0xf2,
0x4a, 0x98, 0x47, 0xf4, 0xc4, 0xfa, 0xc5, 0xda, 0xf6, 0xb7, 0x61, 0x69, 0xbc, 0x0b, 0x44, 0xc2,
0x63, 0x41, 0x6f, 0x5b, 0x06, 0xfe, 0x7b, 0x40, 0xf6, 0xf5, 0x9e, 0x44, 0xdb, 0xc3, 0xe3, 0xcc,
0xcc, 0xb7, 0x07, 0xf5, 0x84, 0x08, 0x71, 0xcd, 0xd3, 0xae, 0xae, 0xaa, 0x6d, 0xdf, 0x87, 0xa5,
0xb3, 0x51, 0x42, 0x8b, 0x3c, 0x08, 0x6a, 0x72, 0x94, 0xe8, 0x1c, 0xea, 0xdb, 0xdf, 0x87, 0xff,
0x6e, 0x19, 0xbe, 0x3b, 0xa8, 0x2e, 0xc0, 0xdc, 0x9b, 0x41, 0x22, 0x47, 0xbb, 0x5f, 0x6b, 0x50,
0x3f, 0x9e, 0xec, 0x60, 0x14, 0x40, 0x2d, 0x2f, 0x89, 0x56, 0xcc, 0x8d, 0x50, 0x51, 0xde, 0x86,
0x39, 0x98, 0xe2, 0xf4, 0x16, 0xc0, 0x74, 0x8c, 0xfe, 0x35, 0x51, 0xa5, 0x35, 0xe7, 0x6d, 0xde,
0xec, 0x9c, 0x24, 0x7a, 0x01, 0x8d, 0x62, 0x9d, 0x20, 0xcf, 0x84, 0xce, 0xee, 0x18, 0x6f, 0x96,
0x5a, 0xbe, 0x22, 0xcc, 0x35, 0xb7, 0x29, 0x94, 0x2e, 0x7f, 0x19, 0xdb, 0x87, 0xf5, 0x1b, 0xe5,
0x43, 0xdb, 0x56, 0x9a, 0xdf, 0x5c, 0x6e, 0xef, 0xe1, 0x9d, 0x71, 0x93, 0xfe, 0x9e, 0x43, 0x2d,
0x1f, 0x21, 0xb4, 0x6e, 0x00, 0xd6, 0xf3, 0x62, 0xeb, 0x3b, 0x35, 0x69, 0x8f, 0x60, 0xae, 0x1d,
0x71, 0x71, 0xc3, 0x1f, 0x29, 0xf5, 0xf2, 0x0a, 0xc0, 0x3c, 0x87, 0xb6, 0x0e, 0xa5, 0x47, 0xb2,
0x84, 0xf5, 0xab, 0xdf, 0x2a, 0xce, 0xd1, 0xe1, 0x87, 0x97, 0x3d, 0x26, 0xfb, 0x59, 0xa7, 0x15,
0xf2, 0x41, 0xd0, 0x27, 0xa2, 0xcf, 0x42, 0x9e, 0x26, 0xc1, 0x90, 0x64, 0x91, 0x0c, 0xee, 0x7c,
0xc9, 0x3b, 0xf3, 0x6a, 0x1f, 0xef, 0xfd, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x9c, 0x49, 0x0b, 0x5b,
0xf5, 0x07, 0x00, 0x00,
}

View File

@ -26,8 +26,9 @@ type AuthEnableCommand struct {
flagAuditNonHMACRequestKeys []string
flagAuditNonHMACResponseKeys []string
flagListingVisibility string
flagPassthroughRequestHeaders []string
flagPluginName string
flagPassthroughRequestHeaders []string
flagAllowedResponseHeaders []string
flagOptions map[string]string
flagLocal bool
flagSealWrap bool
@ -134,7 +135,14 @@ func (c *AuthEnableCommand) Flags() *FlagSets {
Name: flagNamePassthroughRequestHeaders,
Target: &c.flagPassthroughRequestHeaders,
Usage: "Comma-separated string or list of request header values that " +
"will be sent to the backend",
"will be sent to the plugin",
})
f.StringSliceVar(&StringSliceVar{
Name: flagNameAllowedResponseHeaders,
Target: &c.flagAllowedResponseHeaders,
Usage: "Comma-separated string or list of response header values that " +
"plugins will be allowed to set",
})
f.StringVar(&StringVar{
@ -272,6 +280,10 @@ func (c *AuthEnableCommand) Run(args []string) int {
authOpts.Config.PassthroughRequestHeaders = c.flagPassthroughRequestHeaders
}
if fl.Name == flagNameAllowedResponseHeaders {
authOpts.Config.AllowedResponseHeaders = c.flagAllowedResponseHeaders
}
if fl.Name == flagNameTokenType {
authOpts.Config.TokenType = c.flagTokenType
}

View File

@ -76,6 +76,8 @@ const (
flagNameListingVisibility = "listing-visibility"
// flagNamePassthroughRequestHeaders is the flag name used to set passthrough request headers to the backend
flagNamePassthroughRequestHeaders = "passthrough-request-headers"
// flagNameAllowedResponseHeaders is used to set allowed response headers from a plugin
flagNameAllowedResponseHeaders = "allowed-response-headers"
// flagNameTokenType is the flag name used to force a specific token type
flagNameTokenType = "token-type"
)

View File

@ -27,6 +27,7 @@ type SecretsEnableCommand struct {
flagAuditNonHMACResponseKeys []string
flagListingVisibility string
flagPassthroughRequestHeaders []string
flagAllowedResponseHeaders []string
flagForceNoCache bool
flagPluginName string
flagOptions map[string]string
@ -141,7 +142,14 @@ func (c *SecretsEnableCommand) Flags() *FlagSets {
Name: flagNamePassthroughRequestHeaders,
Target: &c.flagPassthroughRequestHeaders,
Usage: "Comma-separated string or list of request header values that " +
"will be sent to the backend",
"will be sent to the plugins",
})
f.StringSliceVar(&StringSliceVar{
Name: flagNameAllowedResponseHeaders,
Target: &c.flagAllowedResponseHeaders,
Usage: "Comma-separated string or list of response header values that " +
"plugins will be allowed to set",
})
f.BoolVar(&BoolVar{
@ -284,6 +292,10 @@ func (c *SecretsEnableCommand) Run(args []string) int {
if fl.Name == flagNamePassthroughRequestHeaders {
mountInput.Config.PassthroughRequestHeaders = c.flagPassthroughRequestHeaders
}
if fl.Name == flagNameAllowedResponseHeaders {
mountInput.Config.AllowedResponseHeaders = c.flagAllowedResponseHeaders
}
})
if err := client.Sys().Mount(mountPath, mountInput); err != nil {

View File

@ -5,9 +5,8 @@ package forwarding
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -6,9 +6,8 @@ package mfa
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -5,11 +5,10 @@ package identity
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
mfa "github.com/hashicorp/vault/helper/identity/mfa"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -5,10 +5,9 @@ package storagepacker
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
any "github.com/golang/protobuf/ptypes/any"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -385,9 +385,19 @@ func MergeSlices(args ...[]string) []string {
// result will also remove any duplicated values in set A regardless of whether
// that matches any values in set B.
func Difference(a, b []string, lowercase bool) []string {
if len(a) == 0 || len(b) == 0 {
if len(a) == 0 {
return a
}
if len(b) == 0 {
if !lowercase {
return a
}
newA := make([]string, len(a))
for i, v := range a {
newA[i] = strings.ToLower(v)
}
return newA
}
a = RemoveDuplicates(a, lowercase)
b = RemoveDuplicates(b, lowercase)

View File

@ -577,6 +577,32 @@ func request(core *vault.Core, w http.ResponseWriter, rawReq *http.Request, r *l
return nil, false, true
}
if resp != nil && len(resp.Headers) > 0 {
// Set this here so it will take effect regardless of any other type of
// response processing
header := w.Header()
for k, v := range resp.Headers {
for _, h := range v {
header.Add(k, h)
}
}
switch {
case resp.Secret != nil,
resp.Auth != nil,
len(resp.Data) > 0,
resp.Redirect != "",
len(resp.Warnings) > 0,
resp.WrapInfo != nil:
// Nothing, resp has data
default:
// We have an otherwise totally empty response except for headers,
// so nil out the response now that the headers are written out
resp = nil
}
}
if respondErrorCommon(w, r, resp, err) {
return resp, false, false
}
@ -634,30 +660,32 @@ func respondStandby(core *vault.Core, w http.ResponseWriter, reqURL *url.URL) {
w.WriteHeader(307)
}
// getTokenFromReq parse headers of the incoming request to extract token if present
// it accepts Authorization Bearer (RFC6750) and X-Vault-Token header
func getTokenFromReq(r *http.Request) (string, error) {
// getTokenFromReq parse headers of the incoming request to extract token if
// present it accepts Authorization Bearer (RFC6750) and X-Vault-Token header.
// Returns true if the token was sourced from a Bearer header.
func getTokenFromReq(r *http.Request) (string, bool) {
if token := r.Header.Get(consts.AuthHeaderName); token != "" {
return token, nil
r.Header.Del(consts.AuthHeaderName)
return token, false
}
if v := r.Header.Get("Authorization"); v != "" {
// Reference for Authorization header format: https://tools.ietf.org/html/rfc7236#section-3
// If string does not start by Bearer, or contains any space after it. It is a formatting error
if !strings.HasPrefix(v, "Bearer ") || strings.LastIndexByte(v, ' ') > 7 {
return "", fmt.Errorf("the Authorization header provided is wrongly formatted. Please use \"Bearer <token>\"")
// If string does not start by 'Bearer ', it is not one we would use,
// but might be used by plugins
if !strings.HasPrefix(v, "Bearer ") {
return "", false
}
return v[7:], nil
return strings.TrimSpace(v[7:]), true
}
return "", nil
return "", false
}
// requestAuth adds the token to the logical.Request if it exists.
func requestAuth(core *vault.Core, r *http.Request, req *logical.Request) (*logical.Request, error) {
// Attach the header value if we have it
if token, err := getTokenFromReq(r); err != nil {
return req, err
} else if token != "" {
token, fromAuthzHeader := getTokenFromReq(r)
if token != "" {
req.ClientToken = token
// Also attach the accessor if we have it. This doesn't fail if it
@ -672,6 +700,10 @@ func requestAuth(core *vault.Core, r *http.Request, req *logical.Request) (*logi
req.ClientTokenAccessor = te.Accessor
req.ClientTokenRemainingUses = te.NumUses
req.SetTokenEntry(te)
if fromAuthzHeader {
// This was a valid token in an authz header
r.Header.Del("Authorization")
}
}
}

View File

@ -558,23 +558,11 @@ func TestHandler_requestAuth(t *testing.T) {
}
}
rInvalidScheme, err := http.NewRequest("GET", "v1/test/path", nil)
if err != nil {
t.Fatalf("err: %s", err)
}
rInvalidScheme.Header.Set("Authorization", "invalid_scheme something")
req := logical.TestRequest(t, logical.ReadOperation, "test/path")
_, err = requestAuth(core, rInvalidScheme, req)
if err == nil {
t.Fatalf("expected an error, got none")
}
rNothing, err := http.NewRequest("GET", "v1/test/path", nil)
if err != nil {
t.Fatalf("err: %s", err)
}
req = logical.TestRequest(t, logical.ReadOperation, "test/path")
req := logical.TestRequest(t, logical.ReadOperation, "test/path")
req, err = requestAuth(core, rNothing, req)
if err != nil {
@ -601,36 +589,39 @@ func TestHandler_requestAuth(t *testing.T) {
func TestHandler_getTokenFromReq(t *testing.T) {
r := http.Request{Header: http.Header{}}
if tok, err := getTokenFromReq(&r); err != nil {
t.Fatalf("expected no error, got %s", err)
} else if tok != "" {
tok, _ := getTokenFromReq(&r)
if tok != "" {
t.Fatalf("expected '' as result, got '%s'", tok)
}
r.Header.Set("Authorization", "Bearer TOKEN NOT_GOOD_TOKEN")
if tok, err := getTokenFromReq(&r); err == nil {
t.Fatalf("expected an error, got none")
} else if tok != "" {
t.Fatalf("expected '' as result, got '%s'", tok)
token, fromHeader := getTokenFromReq(&r)
if !fromHeader {
t.Fatal("expected from header")
} else if token != "TOKEN NOT_GOOD_TOKEN" {
t.Fatal("did not get expected token value")
} else if r.Header.Get("Authorization") == "" {
t.Fatal("expected value to be passed through")
}
r.Header.Set(consts.AuthHeaderName, "NEWTOKEN")
if tok, err := getTokenFromReq(&r); err != nil {
t.Fatalf("expected no error, got %s", err)
} else if tok == "TOKEN" {
tok, _ = getTokenFromReq(&r)
if tok == "TOKEN" {
t.Fatalf("%s header should be prioritized", consts.AuthHeaderName)
} else if tok != "NEWTOKEN" {
t.Fatalf("expected 'NEWTOKEN' as result, got '%s'", tok)
} else if r.Header.Get(consts.AuthHeaderName) != "" {
t.Fatal("expected auth header to be removed")
}
r.Header = http.Header{}
r.Header.Set("Authorization", "Basic TOKEN")
if tok, err := getTokenFromReq(&r); err == nil {
t.Fatal("expected error, got none")
} else if tok != "" {
tok, fromHeader = getTokenFromReq(&r)
if tok != "" {
t.Fatalf("expected '' as result, got '%s'", tok)
} else if fromHeader {
t.Fatal("expected not from header")
}
}
func TestHandler_nonPrintableChars(t *testing.T) {

View File

@ -2,9 +2,9 @@ package http
import (
"encoding/json"
"reflect"
"testing"
"github.com/go-test/deep"
"github.com/hashicorp/vault/vault"
)
@ -45,7 +45,7 @@ func TestSysRotate(t *testing.T) {
expected["request_id"] = actual["request_id"]
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad:\nexpected: %#v\nactual: %#v", expected, actual)
if diff := deep.Equal(actual, expected); diff != nil {
t.Fatal(diff)
}
}

View File

@ -5,9 +5,8 @@ package logical
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -5,9 +5,8 @@ package logical
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -5,16 +5,12 @@ package pb
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
logical "github.com/hashicorp/vault/logical"
)
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -1007,10 +1003,14 @@ type Response struct {
// to user actions without failing the action outright.
Warnings []string `sentinel:"" protobuf:"bytes,5,rep,name=warnings,proto3" json:"warnings,omitempty"`
// Information for wrapping the response in a cubbyhole
WrapInfo *ResponseWrapInfo `sentinel:"" protobuf:"bytes,6,opt,name=wrap_info,json=wrapInfo,proto3" json:"wrap_info,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
WrapInfo *ResponseWrapInfo `sentinel:"" protobuf:"bytes,6,opt,name=wrap_info,json=wrapInfo,proto3" json:"wrap_info,omitempty"`
// Headers will contain the http headers from the response. This value will
// be used in the audit broker to ensure we are auditing only the allowed
// headers.
Headers map[string]*Header `sentinel:"" protobuf:"bytes,7,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
@ -1080,6 +1080,13 @@ func (m *Response) GetWrapInfo() *ResponseWrapInfo {
return nil
}
func (m *Response) GetHeaders() map[string]*Header {
if m != nil {
return m.Headers
}
return nil
}
type ResponseWrapInfo struct {
// Setting to non-zero specifies that the response should be wrapped.
// Specifies the desired TTL of the wrapping token.
@ -2665,6 +2672,7 @@ func init() {
proto.RegisterType((*LeaseOptions)(nil), "pb.LeaseOptions")
proto.RegisterType((*Secret)(nil), "pb.Secret")
proto.RegisterType((*Response)(nil), "pb.Response")
proto.RegisterMapType((map[string]*Header)(nil), "pb.Response.HeadersEntry")
proto.RegisterType((*ResponseWrapInfo)(nil), "pb.ResponseWrapInfo")
proto.RegisterType((*RequestWrapInfo)(nil), "pb.RequestWrapInfo")
proto.RegisterType((*HandleRequestArgs)(nil), "pb.HandleRequestArgs")
@ -2702,6 +2710,168 @@ func init() {
proto.RegisterType((*Connection)(nil), "pb.Connection")
}
func init() { proto.RegisterFile("logical/plugin/pb/backend.proto", fileDescriptor_25821d34acc7c5ef) }
var fileDescriptor_25821d34acc7c5ef = []byte{
// 2495 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, 0x34, 0xff, 0x15, 0x2c, 0xff, 0x82, 0xd7, 0x91,
0x44, 0x2b, 0x12, 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, 0xae, 0x17, 0xcc, 0x5c, 0x9b, 0x7a, 0xbb, 0xa1, 0x17, 0xcf,
0x5c, 0x7f, 0x37, 0x9c, 0xee, 0x4e, 0xa9, 0x7d, 0xc9, 0x7c, 0x67, 0x14, 0xf2, 0x40, 0x04, 0xa4,
0x1c, 0x4e, 0x07, 0x77, 0x67, 0x41, 0x30, 0xf3, 0xd8, 0x2e, 0x4a, 0xa6, 0xf1, 0xf9, 0xae, 0x70,
0xe7, 0x2c, 0x12, 0x74, 0x1e, 0x2a, 0xa3, 0xc1, 0x76, 0x32, 0x8b, 0xeb, 0x30, 0x5f, 0xb8, 0x62,
0xa1, 0xe5, 0x5b, 0xc5, 0xd9, 0x95, 0xd4, 0xac, 0x43, 0xf5, 0x70, 0x1e, 0x8a, 0x85, 0x39, 0x84,
0xda, 0x17, 0x8c, 0x3a, 0x8c, 0x93, 0x6d, 0xa8, 0x5d, 0x60, 0xcb, 0x28, 0x0d, 0x2b, 0x3b, 0x4d,
0x4b, 0xf7, 0xcc, 0x3f, 0x00, 0x9c, 0xca, 0x31, 0x87, 0x9c, 0x07, 0x9c, 0xdc, 0x86, 0x06, 0xe3,
0x7c, 0x22, 0x16, 0x21, 0x33, 0x4a, 0xc3, 0xd2, 0x4e, 0xc7, 0xaa, 0x33, 0xce, 0xc7, 0x8b, 0x90,
0x91, 0xff, 0x03, 0xd9, 0x9c, 0xcc, 0xa3, 0x99, 0x51, 0x1e, 0x96, 0xe4, 0x0c, 0x8c, 0xf3, 0x93,
0x68, 0x96, 0x8c, 0xb1, 0x03, 0x87, 0x19, 0x95, 0x61, 0x69, 0xa7, 0x82, 0x63, 0x0e, 0x02, 0x87,
0x99, 0x7f, 0x29, 0x41, 0xf5, 0x94, 0x8a, 0x8b, 0x88, 0x10, 0xd8, 0xe0, 0x41, 0x20, 0xf4, 0xe2,
0xd8, 0x26, 0x3b, 0xd0, 0x8b, 0x7d, 0x1a, 0x8b, 0x0b, 0x79, 0x22, 0x9b, 0x0a, 0xe6, 0x18, 0x65,
0x54, 0x2f, 0x8b, 0xc9, 0x7b, 0xd0, 0xf1, 0x02, 0x9b, 0x7a, 0x93, 0x48, 0x04, 0x9c, 0xce, 0xe4,
0x3a, 0xd2, 0xae, 0x8d, 0xc2, 0x33, 0x25, 0x23, 0x0f, 0xa1, 0x1f, 0x31, 0xea, 0x4d, 0x5e, 0x71,
0x1a, 0xa6, 0x86, 0x1b, 0x6a, 0x42, 0xa9, 0xf8, 0x86, 0xd3, 0x50, 0xdb, 0x9a, 0xff, 0xa8, 0x41,
0xdd, 0x62, 0x7f, 0x8a, 0x59, 0x24, 0x48, 0x17, 0xca, 0xae, 0x83, 0xa7, 0x6d, 0x5a, 0x65, 0xd7,
0x21, 0x23, 0x20, 0x16, 0x0b, 0x3d, 0xb9, 0xb4, 0x1b, 0xf8, 0x07, 0x5e, 0x1c, 0x09, 0xc6, 0xf5,
0x99, 0xd7, 0x68, 0xc8, 0x1d, 0x68, 0x06, 0x21, 0xe3, 0x28, 0x43, 0x07, 0x34, 0xad, 0x4c, 0x20,
0x0f, 0x1e, 0x52, 0x71, 0x61, 0x6c, 0xa0, 0x02, 0xdb, 0x52, 0xe6, 0x50, 0x41, 0x8d, 0xaa, 0x92,
0xc9, 0x36, 0x31, 0xa1, 0x16, 0x31, 0x9b, 0x33, 0x61, 0xd4, 0x86, 0xa5, 0x9d, 0xd6, 0x1e, 0x8c,
0xc2, 0xe9, 0xe8, 0x0c, 0x25, 0x96, 0xd6, 0x90, 0x3b, 0xb0, 0x21, 0xfd, 0x62, 0xd4, 0xd1, 0xa2,
0x21, 0x2d, 0xf6, 0x63, 0x71, 0x61, 0xa1, 0x94, 0xec, 0x41, 0x5d, 0xdd, 0x69, 0x64, 0x34, 0x86,
0x95, 0x9d, 0xd6, 0x9e, 0x21, 0x0d, 0xf4, 0x29, 0x47, 0x0a, 0x06, 0xd1, 0xa1, 0x2f, 0xf8, 0xc2,
0x4a, 0x0c, 0xc9, 0xbb, 0xd0, 0xb6, 0x3d, 0x97, 0xf9, 0x62, 0x22, 0x82, 0x4b, 0xe6, 0x1b, 0x4d,
0xdc, 0x51, 0x4b, 0xc9, 0xc6, 0x52, 0x44, 0xf6, 0xe0, 0xad, 0xbc, 0xc9, 0x84, 0xda, 0x36, 0x8b,
0xa2, 0x80, 0x1b, 0x80, 0xb6, 0xb7, 0x72, 0xb6, 0xfb, 0x5a, 0x25, 0xa7, 0x75, 0xdc, 0x28, 0xf4,
0xe8, 0x62, 0xe2, 0xd3, 0x39, 0x33, 0x5a, 0x6a, 0x5a, 0x2d, 0xfb, 0x8a, 0xce, 0x19, 0xb9, 0x0b,
0xad, 0x79, 0x10, 0xfb, 0x62, 0x12, 0x06, 0xae, 0x2f, 0x8c, 0x36, 0x5a, 0x00, 0x8a, 0x4e, 0xa5,
0x84, 0xbc, 0x03, 0xaa, 0xa7, 0xc0, 0xd8, 0x51, 0x7e, 0x45, 0x09, 0xc2, 0xf1, 0x1e, 0x74, 0x95,
0x3a, 0xdd, 0x4f, 0x17, 0x4d, 0x3a, 0x28, 0x4d, 0x77, 0xf2, 0x01, 0x34, 0x11, 0x0f, 0xae, 0x7f,
0x1e, 0x18, 0x3d, 0xf4, 0xdb, 0xad, 0x9c, 0x5b, 0x24, 0x26, 0x8e, 0xfc, 0xf3, 0xc0, 0x6a, 0xbc,
0xd2, 0x2d, 0xf2, 0x09, 0xbc, 0x5d, 0x38, 0x2f, 0x67, 0x73, 0xea, 0xfa, 0xae, 0x3f, 0x9b, 0xc4,
0x11, 0x8b, 0x8c, 0x4d, 0x44, 0xb8, 0x91, 0x3b, 0xb5, 0x95, 0x18, 0xbc, 0x8c, 0x58, 0x44, 0xde,
0x86, 0xa6, 0x0a, 0xd0, 0x89, 0xeb, 0x18, 0x7d, 0xdc, 0x52, 0x43, 0x09, 0x8e, 0x1c, 0xf2, 0x00,
0x7a, 0x61, 0xe0, 0xb9, 0xf6, 0x62, 0x12, 0x5c, 0x31, 0xce, 0x5d, 0x87, 0x19, 0x64, 0x58, 0xda,
0x69, 0x58, 0x5d, 0x25, 0xfe, 0x5a, 0x4b, 0xd7, 0x85, 0xc6, 0x2d, 0x34, 0x5c, 0x09, 0x8d, 0x11,
0x80, 0x1d, 0xf8, 0x3e, 0xb3, 0x11, 0x7e, 0x5b, 0x78, 0xc2, 0xae, 0x3c, 0xe1, 0x41, 0x2a, 0xb5,
0x72, 0x16, 0x83, 0xcf, 0xa1, 0x9d, 0x87, 0x02, 0xd9, 0x84, 0xca, 0x25, 0x5b, 0x68, 0xf8, 0xcb,
0x26, 0x19, 0x42, 0xf5, 0x8a, 0x7a, 0x31, 0x43, 0xc8, 0x6b, 0x20, 0xaa, 0x21, 0x96, 0x52, 0xfc,
0xa2, 0xfc, 0xac, 0x64, 0xfe, 0xbd, 0x0a, 0x1b, 0x12, 0x7c, 0xe4, 0x43, 0xe8, 0x78, 0x8c, 0x46,
0x6c, 0x12, 0x84, 0x72, 0x81, 0x08, 0xa7, 0x6a, 0xed, 0x6d, 0xca, 0x61, 0xc7, 0x52, 0xf1, 0xb5,
0x92, 0x5b, 0x6d, 0x2f, 0xd7, 0x93, 0x21, 0xed, 0xfa, 0x82, 0x71, 0x9f, 0x7a, 0x13, 0x0c, 0x06,
0x15, 0x60, 0xed, 0x44, 0xf8, 0x5c, 0x06, 0xc5, 0x32, 0x8e, 0x2a, 0xab, 0x38, 0x1a, 0x40, 0x03,
0x7d, 0xe7, 0xb2, 0x48, 0x07, 0x7b, 0xda, 0x27, 0x7b, 0xd0, 0x98, 0x33, 0x41, 0x75, 0xac, 0xc9,
0x90, 0xd8, 0x4e, 0x62, 0x66, 0x74, 0xa2, 0x15, 0x2a, 0x20, 0x52, 0xbb, 0x95, 0x88, 0xa8, 0xad,
0x46, 0xc4, 0x00, 0x1a, 0x29, 0xe8, 0xea, 0xea, 0x86, 0x93, 0xbe, 0xa4, 0xd9, 0x90, 0x71, 0x37,
0x70, 0x8c, 0x06, 0x02, 0x45, 0xf7, 0x24, 0x49, 0xfa, 0xf1, 0x5c, 0x41, 0xa8, 0xa9, 0x48, 0xd2,
0x8f, 0xe7, 0xab, 0x88, 0x81, 0x25, 0xc4, 0xfc, 0x04, 0xaa, 0xd4, 0x73, 0x69, 0x84, 0x21, 0x24,
0x6f, 0x56, 0xf3, 0xfd, 0x68, 0x5f, 0x4a, 0x2d, 0xa5, 0x24, 0x4f, 0xa1, 0x33, 0xe3, 0x41, 0x1c,
0x4e, 0xb0, 0xcb, 0x22, 0xa3, 0x8d, 0xa7, 0x5d, 0xb6, 0x6e, 0xa3, 0xd1, 0xbe, 0xb2, 0x91, 0x11,
0x38, 0x0d, 0x62, 0xdf, 0x99, 0xd8, 0xae, 0xc3, 0x23, 0xa3, 0x83, 0xce, 0x03, 0x14, 0x1d, 0x48,
0x89, 0x0c, 0x31, 0x15, 0x02, 0xa9, 0x83, 0xbb, 0x68, 0xd3, 0x41, 0xe9, 0x69, 0xe2, 0xe5, 0x9f,
0x42, 0x3f, 0x49, 0x4a, 0x99, 0x65, 0x0f, 0x2d, 0x37, 0x13, 0x45, 0x6a, 0xbc, 0x03, 0x9b, 0xec,
0x5a, 0x52, 0xa8, 0x2b, 0x26, 0x73, 0x7a, 0x3d, 0x11, 0xc2, 0xd3, 0x21, 0xd5, 0x4d, 0xe4, 0x27,
0xf4, 0x7a, 0x2c, 0x3c, 0x19, 0xff, 0x6a, 0x75, 0x8c, 0xff, 0x3e, 0x26, 0xa3, 0x26, 0x4a, 0x64,
0xfc, 0x0f, 0x7e, 0x09, 0x9d, 0xc2, 0x15, 0xae, 0x01, 0xf2, 0x56, 0x1e, 0xc8, 0xcd, 0x3c, 0x78,
0xff, 0xb5, 0x01, 0x80, 0x77, 0xa9, 0x86, 0x2e, 0x67, 0x80, 0xfc, 0x05, 0x97, 0xd7, 0x5c, 0x30,
0xe5, 0xcc, 0x17, 0x1a, 0x8c, 0xba, 0xf7, 0xbd, 0x38, 0x4c, 0x72, 0x40, 0x35, 0x97, 0x03, 0x1e,
0xc1, 0x86, 0xc4, 0x9c, 0x51, 0xcb, 0xa8, 0x3a, 0xdb, 0x11, 0xa2, 0x53, 0x21, 0x13, 0xad, 0x56,
0x02, 0xa1, 0xbe, 0x1a, 0x08, 0x79, 0x84, 0x35, 0x8a, 0x08, 0x7b, 0x0f, 0x3a, 0x36, 0x67, 0x98,
0x8f, 0x26, 0xb2, 0xb0, 0xd0, 0x08, 0x6c, 0x27, 0xc2, 0xb1, 0x3b, 0x67, 0xd2, 0x7f, 0xf2, 0x32,
0x00, 0x55, 0xb2, 0xb9, 0xf6, 0xae, 0x5a, 0x6b, 0xef, 0x0a, 0xb3, 0xbb, 0xc7, 0x34, 0x8b, 0x63,
0x3b, 0x17, 0x09, 0x9d, 0x42, 0x24, 0x14, 0xe0, 0xde, 0x5d, 0x82, 0xfb, 0x12, 0x26, 0x7b, 0x2b,
0x98, 0x7c, 0x17, 0xda, 0xd2, 0x01, 0x51, 0x48, 0x6d, 0x26, 0x27, 0xd8, 0x54, 0x8e, 0x48, 0x65,
0x47, 0x0e, 0x46, 0x70, 0x3c, 0x9d, 0x2e, 0x2e, 0x02, 0x8f, 0x65, 0x24, 0xdc, 0x4a, 0x65, 0x47,
0x8e, 0xdc, 0x2f, 0xa2, 0x8a, 0x20, 0xaa, 0xb0, 0x3d, 0xf8, 0x08, 0x9a, 0xa9, 0xd7, 0x7f, 0x10,
0x98, 0xfe, 0x5a, 0x82, 0x76, 0x9e, 0xe8, 0xe4, 0xe0, 0xf1, 0xf8, 0x18, 0x07, 0x57, 0x2c, 0xd9,
0x94, 0x25, 0x02, 0x67, 0x3e, 0x7b, 0x45, 0xa7, 0x9e, 0x9a, 0xa0, 0x61, 0x65, 0x02, 0xa9, 0x75,
0x7d, 0x9b, 0xb3, 0x79, 0x82, 0xaa, 0x8a, 0x95, 0x09, 0xc8, 0xc7, 0x00, 0x6e, 0x14, 0xc5, 0x4c,
0xdd, 0xdc, 0x06, 0xd2, 0xc0, 0x60, 0xa4, 0xea, 0xc5, 0x51, 0x52, 0x2f, 0x8e, 0xc6, 0x49, 0xbd,
0x68, 0x35, 0xd1, 0x1a, 0xaf, 0x74, 0x1b, 0x6a, 0xf2, 0x82, 0xc6, 0xc7, 0x88, 0xbc, 0x8a, 0xa5,
0x7b, 0xe6, 0x9f, 0xa1, 0xa6, 0x2a, 0x8b, 0xff, 0x29, 0x79, 0xdf, 0x86, 0x86, 0x9a, 0xdb, 0x75,
0x74, 0xac, 0xd4, 0xb1, 0x7f, 0xe4, 0x98, 0xdf, 0x95, 0xa1, 0x61, 0xb1, 0x28, 0x0c, 0xfc, 0x88,
0xe5, 0x2a, 0x9f, 0xd2, 0x6b, 0x2b, 0x9f, 0xf2, 0xda, 0xca, 0x27, 0xa9, 0xa7, 0x2a, 0xb9, 0x7a,
0x6a, 0x00, 0x0d, 0xce, 0x1c, 0x97, 0x33, 0x5b, 0xe8, 0xda, 0x2b, 0xed, 0x4b, 0xdd, 0x2b, 0xca,
0x65, 0xca, 0x8e, 0x30, 0x2f, 0x34, 0xad, 0xb4, 0x4f, 0x9e, 0xe4, 0x0b, 0x06, 0x55, 0x8a, 0x6d,
0xa9, 0x82, 0x41, 0x6d, 0x77, 0x4d, 0xc5, 0xf0, 0x34, 0x2b, 0xbc, 0xea, 0x18, 0xcd, 0xb7, 0xf3,
0x03, 0xd6, 0x57, 0x5e, 0x3f, 0x5a, 0x1e, 0xfe, 0xae, 0x0c, 0x9b, 0xcb, 0x7b, 0x5b, 0x83, 0xc0,
0x2d, 0xa8, 0xaa, 0x7c, 0xa6, 0xe1, 0x2b, 0x56, 0x32, 0x59, 0x65, 0x89, 0xe8, 0x7e, 0xb5, 0x4c,
0x1a, 0xaf, 0x87, 0x5e, 0x91, 0x50, 0xde, 0x87, 0x4d, 0xe9, 0xa2, 0x90, 0x39, 0x59, 0x8d, 0xa6,
0x18, 0xb0, 0xa7, 0xe5, 0x69, 0x95, 0xf6, 0x10, 0xfa, 0x89, 0x69, 0xc6, 0x0d, 0xb5, 0x82, 0xed,
0x61, 0x42, 0x11, 0xdb, 0x50, 0x3b, 0x0f, 0xf8, 0x9c, 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, 0x2d, 0x95, 0x85, 0x6b, 0x1c, 0x99, 0x2d, 0x5f,
0x2e, 0x2c, 0x5f, 0x98, 0xb9, 0xb2, 0x34, 0xf3, 0xef, 0xa0, 0xff, 0x05, 0xf5, 0x1d, 0x8f, 0xe9,
0xf9, 0xf7, 0xf9, 0x2c, 0x92, 0x09, 0x4e, 0xbf, 0x52, 0x26, 0x3a, 0xfb, 0x74, 0xac, 0xa6, 0x96,
0x1c, 0x39, 0xe4, 0x1e, 0xd4, 0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0xea, 0x56, 0x2b, 0xd1, 0x99,
0xdf, 0x02, 0x29, 0x4c, 0x2d, 0x1f, 0x28, 0x0b, 0xb2, 0x23, 0xd1, 0xaf, 0x40, 0xa1, 0xa3, 0xaa,
0x9d, 0xc7, 0xa4, 0x95, 0x6a, 0xc9, 0x10, 0x2a, 0x8c, 0x73, 0xbd, 0x04, 0x16, 0x8e, 0xd9, 0x73,
0xd0, 0x92, 0x2a, 0xf3, 0x67, 0xd0, 0x3f, 0x0b, 0x99, 0xed, 0x52, 0x0f, 0x9f, 0x72, 0x6a, 0x81,
0xbb, 0x50, 0x95, 0x4e, 0x4e, 0x08, 0xa3, 0x89, 0x03, 0x51, 0xad, 0xe4, 0xe6, 0xb7, 0x60, 0xa8,
0x7d, 0x1d, 0x5e, 0xbb, 0x91, 0x60, 0xbe, 0xcd, 0x0e, 0x2e, 0x98, 0x7d, 0xf9, 0x23, 0x9e, 0xfc,
0x0a, 0x6e, 0xaf, 0x5b, 0x21, 0xd9, 0x5f, 0xcb, 0x96, 0xbd, 0xc9, 0xb9, 0xcc, 0x1d, 0xb8, 0x46,
0xc3, 0x02, 0x14, 0x7d, 0x2e, 0x25, 0xf2, 0x1e, 0x99, 0x1c, 0x17, 0x69, 0x3e, 0xd6, 0xbd, 0xc4,
0x1f, 0x95, 0x9b, 0xfd, 0xf1, 0xb7, 0x12, 0x34, 0xcf, 0x98, 0x88, 0x43, 0x3c, 0xcb, 0xdb, 0xd0,
0x9c, 0xf2, 0xe0, 0x92, 0xf1, 0xec, 0x28, 0x0d, 0x25, 0x38, 0x72, 0xc8, 0x13, 0xa8, 0x1d, 0x04,
0xfe, 0xb9, 0x3b, 0xc3, 0x87, 0xad, 0x26, 0x86, 0x74, 0xec, 0x48, 0xe9, 0x14, 0x31, 0x68, 0x43,
0x32, 0x84, 0x96, 0xfe, 0x3c, 0xf0, 0xf2, 0xe5, 0xd1, 0xf3, 0xa4, 0xe2, 0xcd, 0x89, 0x06, 0x1f,
0x43, 0x2b, 0x37, 0xf0, 0x07, 0xa5, 0xaa, 0xff, 0x07, 0xc0, 0xd5, 0x95, 0x8f, 0x36, 0xd5, 0x51,
0xf5, 0x48, 0x79, 0xb4, 0xbb, 0xd0, 0x94, 0xc5, 0x95, 0x52, 0x27, 0x49, 0xb2, 0x94, 0x25, 0x49,
0xf3, 0x1e, 0xf4, 0x8f, 0xfc, 0x2b, 0xea, 0xb9, 0x0e, 0x15, 0xec, 0x4b, 0xb6, 0x40, 0x17, 0xac,
0xec, 0xc0, 0x3c, 0x83, 0xb6, 0x7e, 0x69, 0xbf, 0xd1, 0x1e, 0xdb, 0x7a, 0x8f, 0xdf, 0x1f, 0x44,
0xef, 0x43, 0x4f, 0x4f, 0x7a, 0xec, 0xea, 0x10, 0x92, 0x35, 0x06, 0x67, 0xe7, 0xee, 0xb5, 0x9e,
0x5a, 0xf7, 0xcc, 0x67, 0xb0, 0x99, 0x33, 0x4d, 0x8f, 0x73, 0xc9, 0x16, 0x51, 0xf2, 0x05, 0x42,
0xb6, 0x13, 0x0f, 0x94, 0x33, 0x0f, 0x98, 0xd0, 0xd5, 0x23, 0x5f, 0x30, 0x71, 0xc3, 0xe9, 0xbe,
0x4c, 0x37, 0xf2, 0x82, 0xe9, 0xc9, 0xef, 0x43, 0x95, 0xc9, 0x93, 0xe6, 0xf3, 0x67, 0xde, 0x03,
0x96, 0x52, 0xaf, 0x59, 0xf0, 0x59, 0xba, 0xe0, 0x69, 0xac, 0x16, 0x7c, 0xc3, 0xb9, 0xcc, 0xf7,
0xd2, 0x6d, 0x9c, 0xc6, 0xe2, 0xa6, 0x1b, 0xbd, 0x07, 0x7d, 0x6d, 0xf4, 0x9c, 0x79, 0x4c, 0xb0,
0x1b, 0x8e, 0x74, 0x1f, 0x48, 0xc1, 0xec, 0xa6, 0xe9, 0xee, 0x40, 0x63, 0x3c, 0x3e, 0x4e, 0xb5,
0x45, 0x6e, 0x34, 0x3f, 0x81, 0xfe, 0x59, 0xec, 0x04, 0xa7, 0xdc, 0xbd, 0x72, 0x3d, 0x36, 0x53,
0x8b, 0x25, 0xc5, 0x6f, 0x29, 0x57, 0xfc, 0xae, 0xcd, 0x46, 0xe6, 0x0e, 0x90, 0xc2, 0xf0, 0xf4,
0xde, 0xa2, 0xd8, 0x09, 0x74, 0x08, 0x63, 0xdb, 0xdc, 0x81, 0xf6, 0x98, 0xca, 0x62, 0xc3, 0x51,
0x36, 0x06, 0xd4, 0x85, 0xea, 0x6b, 0xb3, 0xa4, 0x6b, 0xee, 0xc1, 0xd6, 0x01, 0xb5, 0x2f, 0x5c,
0x7f, 0xf6, 0xdc, 0x8d, 0x64, 0xb5, 0xa5, 0x47, 0x0c, 0xa0, 0xe1, 0x68, 0x81, 0x1e, 0x92, 0xf6,
0xcd, 0xc7, 0xf0, 0x56, 0xee, 0x33, 0xcf, 0x99, 0xa0, 0x89, 0x3f, 0xb6, 0xa0, 0x1a, 0xc9, 0x1e,
0x8e, 0xa8, 0x5a, 0xaa, 0x63, 0x7e, 0x05, 0x5b, 0xf9, 0x04, 0x2c, 0x6b, 0x9f, 0xe4, 0xe0, 0x58,
0x95, 0x94, 0x72, 0x55, 0x89, 0xf6, 0x59, 0x39, 0xcb, 0x27, 0x9b, 0x50, 0xf9, 0xf5, 0x37, 0x63,
0x0d, 0x76, 0xd9, 0x34, 0xff, 0x28, 0x97, 0x2f, 0xce, 0xa7, 0x96, 0x2f, 0x94, 0x26, 0xa5, 0x37,
0x2a, 0x4d, 0x56, 0xf1, 0xf6, 0x18, 0xfa, 0x27, 0x5e, 0x60, 0x5f, 0x1e, 0xfa, 0x39, 0x6f, 0x18,
0x50, 0x67, 0x7e, 0xde, 0x19, 0x49, 0xd7, 0x7c, 0x00, 0xbd, 0xe3, 0xc0, 0xa6, 0xde, 0x49, 0x10,
0xfb, 0x22, 0xf5, 0x02, 0x7e, 0x77, 0xd3, 0xa6, 0xaa, 0x63, 0x3e, 0x86, 0xae, 0x4e, 0xd1, 0xfe,
0x79, 0x90, 0x30, 0x63, 0x96, 0xcc, 0x4b, 0xc5, 0x42, 0xdf, 0x3c, 0x86, 0x5e, 0x66, 0xae, 0xe6,
0x7d, 0x00, 0x35, 0xa5, 0xd6, 0x67, 0xeb, 0xa5, 0xaf, 0x57, 0x65, 0x69, 0x69, 0xf5, 0x9a, 0x43,
0xcd, 0xa1, 0x7b, 0x8a, 0xdf, 0x3f, 0x0f, 0xfd, 0x2b, 0x35, 0xd9, 0x11, 0x10, 0xf5, 0x45, 0x74,
0xc2, 0xfc, 0x2b, 0x97, 0x07, 0x3e, 0x16, 0xd7, 0x25, 0x5d, 0xc2, 0x24, 0x13, 0xa7, 0x83, 0x12,
0x0b, 0xab, 0x1f, 0x2e, 0x8b, 0xd6, 0xfa, 0x10, 0xb2, 0xaf, 0x2b, 0x32, 0xd5, 0x70, 0x36, 0x0f,
0x04, 0x9b, 0x50, 0xc7, 0x49, 0xa2, 0x05, 0x94, 0x68, 0xdf, 0x71, 0xf8, 0xde, 0x7f, 0xca, 0x50,
0xff, 0x4c, 0x11, 0x38, 0xf9, 0x14, 0x3a, 0x85, 0x74, 0x4d, 0xde, 0xc2, 0xb2, 0x6e, 0xb9, 0x38,
0x18, 0x6c, 0xaf, 0x88, 0xd5, 0xb9, 0x3e, 0x80, 0x76, 0x3e, 0x19, 0x13, 0x4c, 0xbc, 0xf8, 0xad,
0x77, 0x80, 0x33, 0xad, 0x66, 0xea, 0x33, 0xd8, 0x5a, 0x97, 0x26, 0xc9, 0x9d, 0x6c, 0x85, 0xd5,
0x14, 0x3d, 0x78, 0xe7, 0x26, 0x6d, 0x92, 0x5e, 0xeb, 0x07, 0x1e, 0xa3, 0x7e, 0x1c, 0xe6, 0x77,
0x90, 0x35, 0xc9, 0x13, 0xe8, 0x14, 0x12, 0x85, 0x3a, 0xe7, 0x4a, 0xee, 0xc8, 0x0f, 0xb9, 0x0f,
0x55, 0x4c, 0x4e, 0xa4, 0x53, 0xc8, 0x92, 0x83, 0x6e, 0xda, 0x55, 0x6b, 0x0f, 0x61, 0x03, 0xbf,
0x00, 0xe6, 0x16, 0xc6, 0x11, 0x69, 0xe6, 0xda, 0xfb, 0x77, 0x09, 0xea, 0xc9, 0x57, 0xe1, 0x27,
0xb0, 0x21, 0x73, 0x00, 0xb9, 0x95, 0xa3, 0xd1, 0x24, 0x7f, 0x0c, 0xb6, 0x96, 0x84, 0x6a, 0x81,
0x11, 0x54, 0x5e, 0x30, 0x41, 0x48, 0x4e, 0xa9, 0x93, 0xc1, 0xe0, 0x56, 0x51, 0x96, 0xda, 0x9f,
0xc6, 0x45, 0x7b, 0xcd, 0xe5, 0x05, 0xfb, 0x94, 0xa5, 0x3f, 0x82, 0x9a, 0x62, 0x59, 0xe5, 0x94,
0x15, 0x7e, 0x56, 0x97, 0xbf, 0xca, 0xc7, 0x7b, 0xff, 0xdc, 0x00, 0x38, 0x5b, 0x44, 0x82, 0xcd,
0x7f, 0xe3, 0xb2, 0x57, 0xe4, 0x21, 0xf4, 0x9e, 0xb3, 0x73, 0x1a, 0x7b, 0x02, 0x9f, 0x6a, 0x92,
0x4d, 0x72, 0x3e, 0xc1, 0x82, 0x2f, 0x25, 0xeb, 0xfb, 0xd0, 0x3a, 0xa1, 0xd7, 0xaf, 0xb7, 0xfb,
0x14, 0x3a, 0x05, 0x0e, 0xd6, 0x5b, 0x5c, 0x66, 0x75, 0xbd, 0xc5, 0x55, 0xb6, 0xbe, 0x0f, 0x75,
0xcd, 0xcc, 0xf9, 0x35, 0x30, 0x87, 0x15, 0x18, 0xfb, 0xe7, 0xd0, 0x5b, 0xe2, 0xe5, 0xbc, 0x3d,
0x7e, 0x0e, 0x59, 0xcb, 0xdb, 0xcf, 0xe4, 0x6b, 0xa7, 0xc8, 0xcd, 0xf9, 0x81, 0xfa, 0xe5, 0xb5,
0x8e, 0xbc, 0x5f, 0x14, 0xdf, 0x49, 0xf8, 0x44, 0x35, 0x96, 0xe9, 0x33, 0x21, 0xef, 0xc1, 0xed,
0x75, 0x9a, 0x34, 0x04, 0xf3, 0x0c, 0xba, 0x12, 0x82, 0xab, 0xf4, 0xfa, 0x08, 0x20, 0x23, 0xd1,
0xbc, 0x3d, 0xc2, 0x63, 0x99, 0x5f, 0x3f, 0x04, 0xc8, 0xa8, 0x51, 0xa1, 0xaa, 0xc8, 0xac, 0x6a,
0xd8, 0x32, 0x7d, 0x3e, 0x84, 0x66, 0x4a, 0x67, 0xf9, 0x35, 0x70, 0x82, 0x22, 0x3b, 0x7e, 0x36,
0xfa, 0xfd, 0xa3, 0x99, 0x2b, 0x2e, 0xe2, 0xe9, 0xc8, 0x0e, 0xe6, 0xbb, 0x17, 0x34, 0xba, 0x70,
0xed, 0x80, 0x87, 0xbb, 0x57, 0x12, 0x4c, 0xbb, 0x2b, 0x3f, 0xac, 0xa6, 0x35, 0x7c, 0xec, 0x3d,
0xfd, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x79, 0x37, 0x3d, 0xcc, 0x1a, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
@ -3628,165 +3798,3 @@ var _SystemView_serviceDesc = grpc.ServiceDesc{
Streams: []grpc.StreamDesc{},
Metadata: "logical/plugin/pb/backend.proto",
}
func init() { proto.RegisterFile("logical/plugin/pb/backend.proto", fileDescriptor_25821d34acc7c5ef) }
var fileDescriptor_25821d34acc7c5ef = []byte{
// 2483 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0xcd, 0x72, 0x1b, 0xc7,
0x11, 0x2e, 0x00, 0xc4, 0x5f, 0xe3, 0x8f, 0x18, 0xd1, 0xcc, 0x0a, 0x96, 0x23, 0x78, 0x1d, 0x49,
0xb4, 0x22, 0x81, 0x12, 0x1d, 0xc7, 0x72, 0x52, 0x76, 0x8a, 0xa6, 0x68, 0x99, 0x31, 0x69, 0xb3,
0x96, 0x50, 0x9c, 0xbf, 0x2a, 0x78, 0xb0, 0x3b, 0x04, 0xb7, 0xb8, 0xd8, 0xdd, 0xcc, 0xce, 0x52,
0xc4, 0x29, 0x6f, 0x91, 0xd7, 0xc8, 0x35, 0x95, 0x4b, 0x6e, 0xa9, 0x54, 0x72, 0xce, 0x6b, 0xe4,
0x19, 0x52, 0xd3, 0x33, 0xfb, 0x07, 0x80, 0x96, 0x5c, 0x95, 0xdc, 0x66, 0xba, 0x7b, 0x7a, 0x66,
0x7a, 0xbe, 0xfe, 0xba, 0x17, 0x80, 0xbb, 0x5e, 0x30, 0x73, 0x6d, 0xea, 0xed, 0x86, 0x5e, 0x3c,
0x73, 0xfd, 0xdd, 0x70, 0xba, 0x3b, 0xa5, 0xf6, 0x25, 0xf3, 0x9d, 0x51, 0xc8, 0x03, 0x11, 0x90,
0x72, 0x38, 0x1d, 0xdc, 0x9d, 0x05, 0xc1, 0xcc, 0x63, 0xbb, 0x28, 0x99, 0xc6, 0xe7, 0xbb, 0xc2,
0x9d, 0xb3, 0x48, 0xd0, 0x79, 0xa8, 0x8c, 0x06, 0xdb, 0x89, 0x17, 0xd7, 0x61, 0xbe, 0x70, 0xc5,
0x42, 0xcb, 0xb7, 0x8a, 0xde, 0x95, 0xd4, 0xac, 0x43, 0xf5, 0x70, 0x1e, 0x8a, 0x85, 0x39, 0x84,
0xda, 0x17, 0x8c, 0x3a, 0x8c, 0x93, 0x6d, 0xa8, 0x5d, 0xe0, 0xc8, 0x28, 0x0d, 0x2b, 0x3b, 0x4d,
0x4b, 0xcf, 0xcc, 0xdf, 0x01, 0x9c, 0xca, 0x35, 0x87, 0x9c, 0x07, 0x9c, 0xdc, 0x86, 0x06, 0xe3,
0x7c, 0x22, 0x16, 0x21, 0x33, 0x4a, 0xc3, 0xd2, 0x4e, 0xc7, 0xaa, 0x33, 0xce, 0xc7, 0x8b, 0x90,
0x91, 0x1f, 0x80, 0x1c, 0x4e, 0xe6, 0xd1, 0xcc, 0x28, 0x0f, 0x4b, 0xd2, 0x03, 0xe3, 0xfc, 0x24,
0x9a, 0x25, 0x6b, 0xec, 0xc0, 0x61, 0x46, 0x65, 0x58, 0xda, 0xa9, 0xe0, 0x9a, 0x83, 0xc0, 0x61,
0xe6, 0x9f, 0x4a, 0x50, 0x3d, 0xa5, 0xe2, 0x22, 0x22, 0x04, 0x36, 0x78, 0x10, 0x08, 0xbd, 0x39,
0x8e, 0xc9, 0x0e, 0xf4, 0x62, 0x9f, 0xc6, 0xe2, 0x42, 0xde, 0xc8, 0xa6, 0x82, 0x39, 0x46, 0x19,
0xd5, 0xcb, 0x62, 0xf2, 0x1e, 0x74, 0xbc, 0xc0, 0xa6, 0xde, 0x24, 0x12, 0x01, 0xa7, 0x33, 0xb9,
0x8f, 0xb4, 0x6b, 0xa3, 0xf0, 0x4c, 0xc9, 0xc8, 0x43, 0xe8, 0x47, 0x8c, 0x7a, 0x93, 0x57, 0x9c,
0x86, 0xa9, 0xe1, 0x86, 0x72, 0x28, 0x15, 0xdf, 0x70, 0x1a, 0x6a, 0x5b, 0xf3, 0x6f, 0x35, 0xa8,
0x5b, 0xec, 0x0f, 0x31, 0x8b, 0x04, 0xe9, 0x42, 0xd9, 0x75, 0xf0, 0xb6, 0x4d, 0xab, 0xec, 0x3a,
0x64, 0x04, 0xc4, 0x62, 0xa1, 0x27, 0xb7, 0x76, 0x03, 0xff, 0xc0, 0x8b, 0x23, 0xc1, 0xb8, 0xbe,
0xf3, 0x1a, 0x0d, 0xb9, 0x03, 0xcd, 0x20, 0x64, 0x1c, 0x65, 0x18, 0x80, 0xa6, 0x95, 0x09, 0xe4,
0xc5, 0x43, 0x2a, 0x2e, 0x8c, 0x0d, 0x54, 0xe0, 0x58, 0xca, 0x1c, 0x2a, 0xa8, 0x51, 0x55, 0x32,
0x39, 0x26, 0x26, 0xd4, 0x22, 0x66, 0x73, 0x26, 0x8c, 0xda, 0xb0, 0xb4, 0xd3, 0xda, 0x83, 0x51,
0x38, 0x1d, 0x9d, 0xa1, 0xc4, 0xd2, 0x1a, 0x72, 0x07, 0x36, 0x64, 0x5c, 0x8c, 0x3a, 0x5a, 0x34,
0xa4, 0xc5, 0x7e, 0x2c, 0x2e, 0x2c, 0x94, 0x92, 0x3d, 0xa8, 0xab, 0x37, 0x8d, 0x8c, 0xc6, 0xb0,
0xb2, 0xd3, 0xda, 0x33, 0xa4, 0x81, 0xbe, 0xe5, 0x48, 0xc1, 0x20, 0x3a, 0xf4, 0x05, 0x5f, 0x58,
0x89, 0x21, 0x79, 0x17, 0xda, 0xb6, 0xe7, 0x32, 0x5f, 0x4c, 0x44, 0x70, 0xc9, 0x7c, 0xa3, 0x89,
0x27, 0x6a, 0x29, 0xd9, 0x58, 0x8a, 0xc8, 0x1e, 0xbc, 0x95, 0x37, 0x99, 0x50, 0xdb, 0x66, 0x51,
0x14, 0x70, 0x03, 0xd0, 0xf6, 0x56, 0xce, 0x76, 0x5f, 0xab, 0xa4, 0x5b, 0xc7, 0x8d, 0x42, 0x8f,
0x2e, 0x26, 0x3e, 0x9d, 0x33, 0xa3, 0xa5, 0xdc, 0x6a, 0xd9, 0x57, 0x74, 0xce, 0xc8, 0x5d, 0x68,
0xcd, 0x83, 0xd8, 0x17, 0x93, 0x30, 0x70, 0x7d, 0x61, 0xb4, 0xd1, 0x02, 0x50, 0x74, 0x2a, 0x25,
0xe4, 0x1d, 0x50, 0x33, 0x05, 0xc6, 0x8e, 0x8a, 0x2b, 0x4a, 0x10, 0x8e, 0xf7, 0xa0, 0xab, 0xd4,
0xe9, 0x79, 0xba, 0x68, 0xd2, 0x41, 0x69, 0x7a, 0x92, 0x27, 0xd0, 0x44, 0x3c, 0xb8, 0xfe, 0x79,
0x60, 0xf4, 0x30, 0x6e, 0xb7, 0x72, 0x61, 0x91, 0x98, 0x38, 0xf2, 0xcf, 0x03, 0xab, 0xf1, 0x4a,
0x8f, 0xc8, 0x27, 0xf0, 0x76, 0xe1, 0xbe, 0x9c, 0xcd, 0xa9, 0xeb, 0xbb, 0xfe, 0x6c, 0x12, 0x47,
0x2c, 0x32, 0x36, 0x11, 0xe1, 0x46, 0xee, 0xd6, 0x56, 0x62, 0xf0, 0x32, 0x62, 0x11, 0x79, 0x1b,
0x9a, 0x2a, 0x41, 0x27, 0xae, 0x63, 0xf4, 0xf1, 0x48, 0x0d, 0x25, 0x38, 0x72, 0xc8, 0x03, 0xe8,
0x85, 0x81, 0xe7, 0xda, 0x8b, 0x49, 0x70, 0xc5, 0x38, 0x77, 0x1d, 0x66, 0x90, 0x61, 0x69, 0xa7,
0x61, 0x75, 0x95, 0xf8, 0x6b, 0x2d, 0x5d, 0x97, 0x1a, 0xb7, 0xd0, 0x70, 0x25, 0x35, 0x46, 0x00,
0x76, 0xe0, 0xfb, 0xcc, 0x46, 0xf8, 0x6d, 0xe1, 0x0d, 0xbb, 0xf2, 0x86, 0x07, 0xa9, 0xd4, 0xca,
0x59, 0x0c, 0x3e, 0x87, 0x76, 0x1e, 0x0a, 0x64, 0x13, 0x2a, 0x97, 0x6c, 0xa1, 0xe1, 0x2f, 0x87,
0x64, 0x08, 0xd5, 0x2b, 0xea, 0xc5, 0x0c, 0x21, 0xaf, 0x81, 0xa8, 0x96, 0x58, 0x4a, 0xf1, 0xb3,
0xf2, 0xb3, 0x92, 0xf9, 0xd7, 0x2a, 0x6c, 0x48, 0xf0, 0x91, 0x0f, 0xa1, 0xe3, 0x31, 0x1a, 0xb1,
0x49, 0x10, 0xca, 0x0d, 0x22, 0x74, 0xd5, 0xda, 0xdb, 0x94, 0xcb, 0x8e, 0xa5, 0xe2, 0x6b, 0x25,
0xb7, 0xda, 0x5e, 0x6e, 0x26, 0x53, 0xda, 0xf5, 0x05, 0xe3, 0x3e, 0xf5, 0x26, 0x98, 0x0c, 0x2a,
0xc1, 0xda, 0x89, 0xf0, 0xb9, 0x4c, 0x8a, 0x65, 0x1c, 0x55, 0x56, 0x71, 0x34, 0x80, 0x06, 0xc6,
0xce, 0x65, 0x91, 0x4e, 0xf6, 0x74, 0x4e, 0xf6, 0xa0, 0x31, 0x67, 0x82, 0xea, 0x5c, 0x93, 0x29,
0xb1, 0x9d, 0xe4, 0xcc, 0xe8, 0x44, 0x2b, 0x54, 0x42, 0xa4, 0x76, 0x2b, 0x19, 0x51, 0x5b, 0xcd,
0x88, 0x01, 0x34, 0x52, 0xd0, 0xd5, 0xd5, 0x0b, 0x27, 0x73, 0x49, 0xb3, 0x21, 0xe3, 0x6e, 0xe0,
0x18, 0x0d, 0x04, 0x8a, 0x9e, 0x49, 0x92, 0xf4, 0xe3, 0xb9, 0x82, 0x50, 0x53, 0x91, 0xa4, 0x1f,
0xcf, 0x57, 0x11, 0x03, 0x4b, 0x88, 0xf9, 0x11, 0x54, 0xa9, 0xe7, 0xd2, 0x08, 0x53, 0x48, 0xbe,
0xac, 0xe6, 0xfb, 0xd1, 0xbe, 0x94, 0x5a, 0x4a, 0x49, 0x3e, 0x80, 0xce, 0x8c, 0x07, 0x71, 0x38,
0xc1, 0x29, 0x8b, 0x8c, 0x36, 0xde, 0x76, 0xd9, 0xba, 0x8d, 0x46, 0xfb, 0xca, 0x46, 0x66, 0xe0,
0x34, 0x88, 0x7d, 0x67, 0x62, 0xbb, 0x0e, 0x8f, 0x8c, 0x0e, 0x06, 0x0f, 0x50, 0x74, 0x20, 0x25,
0x32, 0xc5, 0x54, 0x0a, 0xa4, 0x01, 0xee, 0xa2, 0x4d, 0x07, 0xa5, 0xa7, 0x49, 0x94, 0x7f, 0x0c,
0xfd, 0xa4, 0x28, 0x65, 0x96, 0x3d, 0xb4, 0xdc, 0x4c, 0x14, 0xa9, 0xf1, 0x0e, 0x6c, 0xb2, 0x6b,
0x49, 0xa1, 0xae, 0x98, 0xcc, 0xe9, 0xf5, 0x44, 0x08, 0x4f, 0xa7, 0x54, 0x37, 0x91, 0x9f, 0xd0,
0xeb, 0xb1, 0xf0, 0x64, 0xfe, 0xab, 0xdd, 0x31, 0xff, 0xfb, 0x58, 0x8c, 0x9a, 0x28, 0x91, 0xf9,
0x3f, 0xf8, 0x39, 0x74, 0x0a, 0x4f, 0xb8, 0x06, 0xc8, 0x5b, 0x79, 0x20, 0x37, 0xf3, 0xe0, 0xfd,
0xe7, 0x06, 0x00, 0xbe, 0xa5, 0x5a, 0xba, 0x5c, 0x01, 0xf2, 0x0f, 0x5c, 0x5e, 0xf3, 0xc0, 0x94,
0x33, 0x5f, 0x68, 0x30, 0xea, 0xd9, 0x77, 0xe2, 0x30, 0xa9, 0x01, 0xd5, 0x5c, 0x0d, 0x78, 0x04,
0x1b, 0x12, 0x73, 0x46, 0x2d, 0xa3, 0xea, 0xec, 0x44, 0x88, 0x4e, 0x85, 0x4c, 0xb4, 0x5a, 0x49,
0x84, 0xfa, 0x6a, 0x22, 0xe4, 0x11, 0xd6, 0x28, 0x22, 0xec, 0x3d, 0xe8, 0xd8, 0x9c, 0x61, 0x3d,
0x9a, 0xc8, 0xc6, 0x42, 0x23, 0xb0, 0x9d, 0x08, 0xc7, 0xee, 0x9c, 0xc9, 0xf8, 0xc9, 0xc7, 0x00,
0x54, 0xc9, 0xe1, 0xda, 0xb7, 0x6a, 0xad, 0x7d, 0x2b, 0xac, 0xee, 0x1e, 0xd3, 0x2c, 0x8e, 0xe3,
0x5c, 0x26, 0x74, 0x0a, 0x99, 0x50, 0x80, 0x7b, 0x77, 0x09, 0xee, 0x4b, 0x98, 0xec, 0xad, 0x60,
0xf2, 0x5d, 0x68, 0xcb, 0x00, 0x44, 0x21, 0xb5, 0x99, 0x74, 0xb0, 0xa9, 0x02, 0x91, 0xca, 0x8e,
0x1c, 0xcc, 0xe0, 0x78, 0x3a, 0x5d, 0x5c, 0x04, 0x1e, 0xcb, 0x48, 0xb8, 0x95, 0xca, 0x8e, 0x1c,
0x79, 0x5e, 0x44, 0x15, 0x41, 0x54, 0xe1, 0x78, 0xf0, 0x11, 0x34, 0xd3, 0xa8, 0x7f, 0x2f, 0x30,
0xfd, 0xb9, 0x04, 0xed, 0x3c, 0xd1, 0xc9, 0xc5, 0xe3, 0xf1, 0x31, 0x2e, 0xae, 0x58, 0x72, 0x28,
0x5b, 0x04, 0xce, 0x7c, 0xf6, 0x8a, 0x4e, 0x3d, 0xe5, 0xa0, 0x61, 0x65, 0x02, 0xa9, 0x75, 0x7d,
0x9b, 0xb3, 0x79, 0x82, 0xaa, 0x8a, 0x95, 0x09, 0xc8, 0xc7, 0x00, 0x6e, 0x14, 0xc5, 0x4c, 0xbd,
0xdc, 0x06, 0xd2, 0xc0, 0x60, 0xa4, 0xfa, 0xc5, 0x51, 0xd2, 0x2f, 0x8e, 0xc6, 0x49, 0xbf, 0x68,
0x35, 0xd1, 0x1a, 0x9f, 0x74, 0x1b, 0x6a, 0xf2, 0x81, 0xc6, 0xc7, 0x88, 0xbc, 0x8a, 0xa5, 0x67,
0xe6, 0x1f, 0xa1, 0xa6, 0x3a, 0x8b, 0xff, 0x2b, 0x79, 0xdf, 0x86, 0x86, 0xf2, 0xed, 0x3a, 0x3a,
0x57, 0xea, 0x38, 0x3f, 0x72, 0xcc, 0x7f, 0x95, 0xa0, 0x61, 0xb1, 0x28, 0x0c, 0xfc, 0x88, 0xe5,
0x3a, 0x9f, 0xd2, 0x6b, 0x3b, 0x9f, 0xf2, 0xda, 0xce, 0x27, 0xe9, 0xa7, 0x2a, 0xb9, 0x7e, 0x6a,
0x00, 0x0d, 0xce, 0x1c, 0x97, 0x33, 0x5b, 0xe8, 0xde, 0x2b, 0x9d, 0x4b, 0xdd, 0x2b, 0xca, 0x65,
0xc9, 0x8e, 0xb0, 0x2e, 0x34, 0xad, 0x74, 0x4e, 0x9e, 0xe6, 0x1b, 0x06, 0xd5, 0x8a, 0x6d, 0xa9,
0x86, 0x41, 0x1d, 0x77, 0xb5, 0x63, 0x30, 0xff, 0x51, 0x86, 0xcd, 0x65, 0xf5, 0x1a, 0x10, 0x6c,
0x41, 0x55, 0x95, 0x14, 0x8d, 0x20, 0xb1, 0x52, 0x4c, 0x2a, 0x4b, 0x5c, 0xf3, 0x8b, 0xe5, 0xbc,
0x7d, 0xfd, 0xeb, 0x17, 0x73, 0xfa, 0x7d, 0xd8, 0x94, 0xa7, 0x0c, 0x99, 0x93, 0xb5, 0x49, 0x8a,
0x84, 0x7a, 0x5a, 0x9e, 0x36, 0x4a, 0x0f, 0xa1, 0x9f, 0x98, 0x66, 0xe9, 0x59, 0x2b, 0xd8, 0x1e,
0x26, 0x59, 0xba, 0x0d, 0xb5, 0xf3, 0x80, 0xcf, 0xa9, 0xd0, 0x3c, 0xa4, 0x67, 0x05, 0x9e, 0x41,
0xc2, 0x6b, 0x28, 0x58, 0x24, 0x42, 0xf9, 0x29, 0x20, 0xf3, 0x3f, 0x6d, 0xd3, 0x91, 0x88, 0x1a,
0x56, 0x23, 0x69, 0xcf, 0xcd, 0x5f, 0x43, 0x6f, 0xa9, 0x33, 0x5b, 0x13, 0xc8, 0x6c, 0xfb, 0x72,
0x61, 0xfb, 0x82, 0xe7, 0xca, 0x92, 0xe7, 0xdf, 0x40, 0xff, 0x0b, 0xea, 0x3b, 0x1e, 0xd3, 0xfe,
0xf7, 0xf9, 0x2c, 0x92, 0x35, 0x46, 0x7f, 0x28, 0x4c, 0x74, 0x01, 0xe8, 0x58, 0x4d, 0x2d, 0x39,
0x72, 0xc8, 0x3d, 0xa8, 0x73, 0x65, 0xad, 0x81, 0xd7, 0xca, 0xb5, 0x8e, 0x56, 0xa2, 0x33, 0xbf,
0x05, 0x52, 0x70, 0x2d, 0xbf, 0x11, 0x16, 0x64, 0x47, 0x02, 0x50, 0x81, 0x42, 0x03, 0xbb, 0x9d,
0xc7, 0x91, 0x95, 0x6a, 0xc9, 0x10, 0x2a, 0x8c, 0x73, 0xbd, 0x05, 0xf6, 0x6e, 0xd9, 0x17, 0x99,
0x25, 0x55, 0xe6, 0x4f, 0xa0, 0x7f, 0x16, 0x32, 0xdb, 0xa5, 0x1e, 0x7e, 0x4d, 0xa9, 0x0d, 0xee,
0x42, 0x55, 0x06, 0x39, 0xc9, 0xd9, 0x26, 0x2e, 0x44, 0xb5, 0x92, 0x9b, 0xdf, 0x82, 0xa1, 0xce,
0x75, 0x78, 0xed, 0x46, 0x82, 0xf9, 0x36, 0x3b, 0xb8, 0x60, 0xf6, 0xe5, 0xff, 0xf0, 0xe6, 0x57,
0x70, 0x7b, 0xdd, 0x0e, 0xc9, 0xf9, 0x5a, 0xb6, 0x9c, 0x4d, 0xce, 0x25, 0x7d, 0xe3, 0x1e, 0x0d,
0x0b, 0x50, 0xf4, 0xb9, 0x94, 0xc8, 0x77, 0x64, 0x72, 0x5d, 0xa4, 0x29, 0x51, 0xcf, 0x92, 0x78,
0x54, 0x6e, 0x8e, 0xc7, 0x5f, 0x4a, 0xd0, 0x3c, 0x63, 0x22, 0x0e, 0xf1, 0x2e, 0x6f, 0x43, 0x73,
0xca, 0x83, 0x4b, 0xc6, 0xb3, 0xab, 0x34, 0x94, 0xe0, 0xc8, 0x21, 0x4f, 0xa1, 0x76, 0x10, 0xf8,
0xe7, 0xee, 0x0c, 0xbf, 0x2d, 0x5b, 0x7b, 0xb7, 0x15, 0xbb, 0xe8, 0xb5, 0x23, 0xa5, 0x53, 0xa5,
0x56, 0x1b, 0x92, 0x21, 0xb4, 0xf4, 0x17, 0xfa, 0xcb, 0x97, 0x47, 0xcf, 0x93, 0xa6, 0x33, 0x27,
0x1a, 0x7c, 0x0c, 0xad, 0xdc, 0xc2, 0xef, 0x55, 0x2d, 0x7e, 0x08, 0x80, 0xbb, 0xab, 0x18, 0x6d,
0xaa, 0xab, 0xea, 0x95, 0xf2, 0x6a, 0x77, 0xa1, 0x29, 0xfb, 0x1b, 0xa5, 0x4e, 0xea, 0x54, 0x29,
0xab, 0x53, 0xe6, 0x3d, 0xe8, 0x1f, 0xf9, 0x57, 0xd4, 0x73, 0x1d, 0x2a, 0xd8, 0x97, 0x6c, 0x81,
0x21, 0x58, 0x39, 0x81, 0x79, 0x06, 0x6d, 0xfd, 0xb1, 0xfb, 0x46, 0x67, 0x6c, 0xeb, 0x33, 0x7e,
0x77, 0x12, 0xbd, 0x0f, 0x3d, 0xed, 0xf4, 0xd8, 0xd5, 0x29, 0x24, 0xcb, 0x3c, 0x67, 0xe7, 0xee,
0xb5, 0x76, 0xad, 0x67, 0xe6, 0x33, 0xd8, 0xcc, 0x99, 0xa6, 0xd7, 0xb9, 0x64, 0x8b, 0x28, 0xf9,
0x11, 0x40, 0x8e, 0x93, 0x08, 0x94, 0xb3, 0x08, 0x98, 0xd0, 0xd5, 0x2b, 0x5f, 0x30, 0x71, 0xc3,
0xed, 0xbe, 0x4c, 0x0f, 0xf2, 0x82, 0x69, 0xe7, 0xf7, 0xa1, 0xca, 0xe4, 0x4d, 0xf3, 0x25, 0x2c,
0x1f, 0x01, 0x4b, 0xa9, 0xd7, 0x6c, 0xf8, 0x2c, 0xdd, 0xf0, 0x34, 0x56, 0x1b, 0xbe, 0xa1, 0x2f,
0xf3, 0xbd, 0xf4, 0x18, 0xa7, 0xb1, 0xb8, 0xe9, 0x45, 0xef, 0x41, 0x5f, 0x1b, 0x3d, 0x67, 0x1e,
0x13, 0xec, 0x86, 0x2b, 0xdd, 0x07, 0x52, 0x30, 0xbb, 0xc9, 0xdd, 0x1d, 0x68, 0x8c, 0xc7, 0xc7,
0xa9, 0xb6, 0xc8, 0x8d, 0xe6, 0x27, 0xd0, 0x3f, 0x8b, 0x9d, 0xe0, 0x94, 0xbb, 0x57, 0xae, 0xc7,
0x66, 0x6a, 0xb3, 0xa4, 0xff, 0x2c, 0xe5, 0xfa, 0xcf, 0xb5, 0xd5, 0xc8, 0xdc, 0x01, 0x52, 0x58,
0x9e, 0xbe, 0x5b, 0x14, 0x3b, 0x81, 0x4e, 0x61, 0x1c, 0x9b, 0x3b, 0xd0, 0x1e, 0x53, 0x59, 0xef,
0x1d, 0x65, 0x63, 0x40, 0x5d, 0xa8, 0xb9, 0x36, 0x4b, 0xa6, 0xe6, 0x1e, 0x6c, 0x1d, 0x50, 0xfb,
0xc2, 0xf5, 0x67, 0xcf, 0xdd, 0x48, 0x36, 0x3c, 0x7a, 0xc5, 0x00, 0x1a, 0x8e, 0x16, 0xe8, 0x25,
0xe9, 0xdc, 0x7c, 0x0c, 0x6f, 0xe5, 0x7e, 0x69, 0x39, 0x13, 0x34, 0x89, 0xc7, 0x16, 0x54, 0x23,
0x39, 0xc3, 0x15, 0x55, 0x4b, 0x4d, 0xcc, 0xaf, 0x60, 0x2b, 0x5f, 0x80, 0x65, 0xfb, 0x91, 0x5c,
0x1c, 0x1b, 0x83, 0x52, 0xae, 0x31, 0xd0, 0x31, 0x2b, 0x67, 0xf5, 0x64, 0x13, 0x2a, 0xbf, 0xfc,
0x66, 0xac, 0xc1, 0x2e, 0x87, 0xe6, 0xef, 0xe5, 0xf6, 0x45, 0x7f, 0x6a, 0xfb, 0x42, 0x77, 0x50,
0x7a, 0x93, 0xee, 0x60, 0x0d, 0xde, 0x1e, 0x43, 0xff, 0xc4, 0x0b, 0xec, 0xcb, 0x43, 0x3f, 0x17,
0x0d, 0x03, 0xea, 0xcc, 0xcf, 0x07, 0x23, 0x99, 0x9a, 0x0f, 0xa0, 0x77, 0x1c, 0xd8, 0xd4, 0x3b,
0x09, 0x62, 0x5f, 0xa4, 0x51, 0xc0, 0x9f, 0xbe, 0xb4, 0xa9, 0x9a, 0x98, 0x8f, 0xa1, 0xab, 0x4b,
0xb4, 0x7f, 0x1e, 0x24, 0xcc, 0x98, 0x15, 0xf3, 0x52, 0xb1, 0xd7, 0x36, 0x8f, 0xa1, 0x97, 0x99,
0x2b, 0xbf, 0x0f, 0xa0, 0xa6, 0xd4, 0xfa, 0x6e, 0xbd, 0xf4, 0x03, 0x52, 0x59, 0x5a, 0x5a, 0xbd,
0xe6, 0x52, 0x73, 0xe8, 0x9e, 0xe2, 0x4f, 0x90, 0x87, 0xfe, 0x95, 0x72, 0x76, 0x04, 0x44, 0xfd,
0x28, 0x39, 0x61, 0xfe, 0x95, 0xcb, 0x03, 0x1f, 0xfb, 0xdb, 0x92, 0x6e, 0x61, 0x12, 0xc7, 0xe9,
0xa2, 0xc4, 0xc2, 0xea, 0x87, 0xcb, 0xa2, 0xb5, 0x31, 0x84, 0xec, 0x07, 0x0e, 0x59, 0x6a, 0x38,
0x9b, 0x07, 0x82, 0x4d, 0xa8, 0xe3, 0x24, 0xd9, 0x02, 0x4a, 0xb4, 0xef, 0x38, 0x7c, 0xef, 0x3f,
0x65, 0xa8, 0x7f, 0xa6, 0x08, 0x9c, 0x7c, 0x0a, 0x9d, 0x42, 0xb9, 0x26, 0x6f, 0xe1, 0x2f, 0x1c,
0xcb, 0xcd, 0xc1, 0x60, 0x7b, 0x45, 0xac, 0xee, 0xf5, 0x04, 0xda, 0xf9, 0x62, 0x4c, 0xb0, 0xf0,
0xe2, 0xcf, 0xad, 0x03, 0xf4, 0xb4, 0x5a, 0xa9, 0xcf, 0x60, 0x6b, 0x5d, 0x99, 0x24, 0x77, 0xb2,
0x1d, 0x56, 0x4b, 0xf4, 0xe0, 0x9d, 0x9b, 0xb4, 0x49, 0x79, 0xad, 0x1f, 0x78, 0x8c, 0xfa, 0x71,
0x98, 0x3f, 0x41, 0x36, 0x24, 0x4f, 0xa1, 0x53, 0x28, 0x14, 0xea, 0x9e, 0x2b, 0xb5, 0x23, 0xbf,
0xe4, 0x3e, 0x54, 0xb1, 0x38, 0x91, 0x4e, 0xa1, 0x4a, 0x0e, 0xba, 0xe9, 0x54, 0xed, 0x3d, 0x84,
0x0d, 0xfc, 0x11, 0x2e, 0xb7, 0x31, 0xae, 0x48, 0x2b, 0xd7, 0xde, 0xbf, 0x4b, 0x50, 0x4f, 0x7e,
0x98, 0x7d, 0x0a, 0x1b, 0xb2, 0x06, 0x90, 0x5b, 0x39, 0x1a, 0x4d, 0xea, 0xc7, 0x60, 0x6b, 0x49,
0xa8, 0x36, 0x18, 0x41, 0xe5, 0x05, 0x13, 0x84, 0xe4, 0x94, 0xba, 0x18, 0x0c, 0x6e, 0x15, 0x65,
0xa9, 0xfd, 0x69, 0x5c, 0xb4, 0xd7, 0x5c, 0x5e, 0xb0, 0x4f, 0x59, 0xfa, 0x23, 0xa8, 0x29, 0x96,
0x55, 0x41, 0x59, 0xe1, 0x67, 0xf5, 0xf8, 0xab, 0x7c, 0xbc, 0xf7, 0xf7, 0x0d, 0x80, 0xb3, 0x45,
0x24, 0xd8, 0xfc, 0x57, 0x2e, 0x7b, 0x45, 0x1e, 0x42, 0xef, 0x39, 0x3b, 0xa7, 0xb1, 0x27, 0xf0,
0x6b, 0x49, 0xb2, 0x49, 0x2e, 0x26, 0xd8, 0xf0, 0xa5, 0x64, 0x7d, 0x1f, 0x5a, 0x27, 0xf4, 0xfa,
0xf5, 0x76, 0x9f, 0x42, 0xa7, 0xc0, 0xc1, 0xfa, 0x88, 0xcb, 0xac, 0xae, 0x8f, 0xb8, 0xca, 0xd6,
0xf7, 0xa1, 0xae, 0x99, 0x39, 0xbf, 0x07, 0xd6, 0xb0, 0x02, 0x63, 0xff, 0x14, 0x7a, 0x4b, 0xbc,
0x9c, 0xb7, 0xc7, 0x5f, 0x24, 0xd6, 0xf2, 0xf6, 0x33, 0xf9, 0xb5, 0x53, 0xe4, 0xe6, 0xfc, 0xc2,
0xdb, 0x8a, 0x0f, 0xd7, 0x91, 0xf7, 0x8b, 0xe2, 0x77, 0x12, 0x7e, 0x25, 0x1a, 0xcb, 0xf4, 0x99,
0x90, 0x77, 0xe2, 0x68, 0x1d, 0x0d, 0x3f, 0x81, 0x76, 0x9e, 0x41, 0x57, 0x52, 0x70, 0x95, 0x5e,
0x1f, 0x01, 0x64, 0x24, 0x9a, 0xb7, 0x47, 0x78, 0x2c, 0xf3, 0xeb, 0x87, 0x00, 0x19, 0x35, 0x2a,
0x54, 0x15, 0x99, 0x55, 0x2d, 0x5b, 0xa6, 0xcf, 0x87, 0xd0, 0x4c, 0xe9, 0x2c, 0xbf, 0x07, 0x3a,
0x28, 0xb2, 0xe3, 0x67, 0xa3, 0xdf, 0x3e, 0x9a, 0xb9, 0xe2, 0x22, 0x9e, 0x8e, 0xec, 0x60, 0xbe,
0x7b, 0x41, 0xa3, 0x0b, 0xd7, 0x0e, 0x78, 0xb8, 0x7b, 0x25, 0xc1, 0xb4, 0xbb, 0xf2, 0x9f, 0xd1,
0xb4, 0x86, 0x1f, 0x7b, 0x1f, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x93, 0x15, 0xb9, 0x42, 0x4f,
0x1a, 0x00, 0x00,
}

View File

@ -285,6 +285,11 @@ message Response {
// Information for wrapping the response in a cubbyhole
ResponseWrapInfo wrap_info = 6;
// Headers will contain the http headers from the response. This value will
// be used in the audit broker to ensure we are auditing only the allowed
// headers.
map<string, Header> headers = 7;
}
message ResponseWrapInfo {

View File

@ -373,6 +373,14 @@ func ProtoResponseToLogicalResponse(r *Response) (*logical.Response, error) {
return nil, err
}
var headers map[string][]string
if len(r.Headers) > 0 {
headers = make(map[string][]string, len(r.Headers))
for k, v := range r.Headers {
headers[k] = v.Header
}
}
return &logical.Response{
Secret: secret,
Auth: auth,
@ -380,6 +388,7 @@ func ProtoResponseToLogicalResponse(r *Response) (*logical.Response, error) {
Redirect: r.Redirect,
Warnings: r.Warnings,
WrapInfo: wrapInfo,
Headers: headers,
}, nil
}
@ -454,6 +463,11 @@ func LogicalResponseToProtoResponse(r *logical.Response) (*Response, error) {
return nil, err
}
headers := map[string]*Header{}
for k, v := range r.Headers {
headers[k] = &Header{Header: v}
}
return &Response{
Secret: secret,
Auth: auth,
@ -461,6 +475,7 @@ func LogicalResponseToProtoResponse(r *logical.Response) (*Response, error) {
Redirect: r.Redirect,
Warnings: r.Warnings,
WrapInfo: wrapInfo,
Headers: headers,
}, nil
}

View File

@ -61,6 +61,10 @@ type Response struct {
// Information for wrapping the response in a cubbyhole
WrapInfo *wrapping.ResponseWrapInfo `json:"wrap_info" structs:"wrap_info" mapstructure:"wrap_info"`
// Headers will contain the http headers from the plugin that it wishes to
// have as part of the output
Headers map[string][]string `json:"headers" structs:"headers" mapstructure:"headers"`
}
// AddWarning adds a warning into the response's warning list

View File

@ -15,6 +15,7 @@ func LogicalResponseToHTTPResponse(input *Response) *HTTPResponse {
httpResp := &HTTPResponse{
Data: input.Data,
Warnings: input.Warnings,
Headers: input.Headers,
}
if input.Secret != nil {
@ -47,6 +48,7 @@ func HTTPResponseToLogicalResponse(input *HTTPResponse) *Response {
logicalResp := &Response{
Data: input.Data,
Warnings: input.Warnings,
Headers: input.Headers,
}
if input.LeaseID != "" {
@ -88,6 +90,7 @@ type HTTPResponse struct {
Data map[string]interface{} `json:"data"`
WrapInfo *HTTPWrapInfo `json:"wrap_info"`
Warnings []string `json:"warnings"`
Headers map[string][]string `json:"-"`
Auth *HTTPAuth `json:"auth"`
}

View File

@ -5,9 +5,8 @@ package physical
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -2255,7 +2255,6 @@ func TestCore_Standby_Rotate(t *testing.T) {
}
}
// Ensure that InternalData is never returned
func TestCore_HandleRequest_Headers(t *testing.T) {
noop := &NoopBackend{
Response: &logical.Response{
@ -2295,6 +2294,7 @@ func TestCore_HandleRequest_Headers(t *testing.T) {
"Should-Passthrough": []string{"foo"},
"Should-Passthrough-Case-Insensitive": []string{"baz"},
"Should-Not-Passthrough": []string{"bar"},
consts.AuthHeaderName: []string{"nope"},
},
}
_, err = c.HandleRequest(namespace.RootContext(nil), lreq)
@ -2321,11 +2321,15 @@ func TestCore_HandleRequest_Headers(t *testing.T) {
t.Fatalf("expected: %v, got: %v", expected, val)
}
} else {
t.Fatalf("expected 'Should-Passthrough-Case-Insensitive' to be present in the headers map")
t.Fatal("expected 'Should-Passthrough-Case-Insensitive' to be present in the headers map")
}
if _, ok := headers["Should-Not-Passthrough"]; ok {
t.Fatalf("did not expect 'Should-Not-Passthrough' to be in the headers map")
t.Fatal("did not expect 'Should-Not-Passthrough' to be in the headers map")
}
if _, ok := headers[consts.AuthHeaderName]; ok {
t.Fatalf("did not expect %q to be in the headers map", consts.AuthHeaderName)
}
}
@ -2366,7 +2370,6 @@ func TestCore_HandleRequest_Headers_denyList(t *testing.T) {
ClientToken: root,
Headers: map[string][]string{
consts.AuthHeaderName: []string{"foo"},
"Authorization": []string{"baz"},
},
}
_, err = c.HandleRequest(namespace.RootContext(nil), lreq)
@ -2378,10 +2381,6 @@ func TestCore_HandleRequest_Headers_denyList(t *testing.T) {
headers := noop.Requests[0].Headers
// Test passthrough values, they should not be present in the backend
if _, ok := headers["Authorization"]; ok {
t.Fatalf("did not expect 'Should-Not-Passthrough' to be in the headers map")
}
if _, ok := headers[consts.AuthHeaderName]; ok {
t.Fatalf("did not expect %q to be in the headers map", consts.AuthHeaderName)
}

View File

@ -0,0 +1,141 @@
package identity
import (
"context"
"testing"
"github.com/hashicorp/vault/api"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
"github.com/hashicorp/vault/vault"
"github.com/kr/pretty"
)
func TestIdentityStore_EntityDisabled(t *testing.T) {
be := &framework.Backend{
PathsSpecial: &logical.Paths{
Unauthenticated: []string{
"login*",
},
},
Paths: []*framework.Path{
{
Pattern: "login",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: func(context.Context, *logical.Request, *framework.FieldData) (*logical.Response, error) {
return &logical.Response{
Headers: map[string][]string{
"www-authenticate": []string{"Negotiate"},
},
}, logical.CodedError(401, "authentication required")
},
},
},
{
Pattern: "loginnoerror",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: func(context.Context, *logical.Request, *framework.FieldData) (*logical.Response, error) {
return &logical.Response{
Auth: &logical.Auth{},
Headers: map[string][]string{
"www-authenticate": []string{"Negotiate"},
},
}, nil
},
},
},
},
BackendType: logical.TypeCredential,
}
// Use a TestCluster and the approle backend to get a token and entity for testing
coreConfig := &vault.CoreConfig{
CredentialBackends: map[string]logical.Factory{
"headtest": func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
err := be.Setup(ctx, conf)
if err != nil {
return nil, err
}
return be, nil
},
},
}
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
HandlerFunc: vaulthttp.Handler,
})
cluster.Start()
defer cluster.Cleanup()
core := cluster.Cores[0].Core
vault.TestWaitActive(t, core)
client := cluster.Cores[0].Client
// Mount the auth backend
err := client.Sys().EnableAuthWithOptions("headtest", &api.EnableAuthOptions{
Type: "headtest",
})
if err != nil {
t.Fatal(err)
}
// Here, should suceed but we should not see the header since it's
// not in the allowed list
req := client.NewRequest("GET", "/v1/auth/headtest/loginnoerror")
resp, err := client.RawRequest(req)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != 200 {
t.Fatalf("expected code 200, got %d", resp.StatusCode)
}
if resp.Header.Get("www-authenticate") != "" {
t.Fatal("expected header to not be allowed")
}
// Should fail but we should not see the header since it's
// not in the allowed list
req = client.NewRequest("GET", "/v1/auth/headtest/login")
resp, err = client.RawRequest(req)
if err == nil {
t.Fatal("expected error")
}
if resp.StatusCode != 401 {
t.Fatalf("expected code 401, got %d", resp.StatusCode)
}
if resp.Header.Get("www-authenticate") != "" {
t.Fatal("expected header to not be allowed")
}
// Tune the mount
err = client.Sys().TuneMount("auth/headtest", api.MountConfigInput{
AllowedResponseHeaders: []string{"WwW-AuthenTicate"},
})
if err != nil {
t.Fatal(err)
}
req = client.NewRequest("GET", "/v1/auth/headtest/loginnoerror")
resp, err = client.RawRequest(req)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != 200 {
t.Fatalf("expected code 200, got %d", resp.StatusCode)
}
if resp.Header.Get("www-authenticate") != "Negotiate" {
t.Fatalf("expected negotiate header; headers:\n%s", pretty.Sprint(resp.Header))
}
req = client.NewRequest("GET", "/v1/auth/headtest/login")
resp, err = client.RawRequest(req)
if err == nil {
t.Fatal("expected error")
}
if resp.StatusCode != 401 {
t.Fatalf("expected code 401, got %d", resp.StatusCode)
}
if resp.Header.Get("www-authenticate") != "Negotiate" {
t.Fatalf("expected negotiate header; headers:\n%s", pretty.Sprint(resp.Header))
}
}

View File

@ -679,6 +679,9 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
if rawVal, ok := entry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
entryConfig["passthrough_request_headers"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("allowed_response_headers"); ok {
entryConfig["allowed_response_headers"] = rawVal.([]string)
}
if entry.Table == credentialTableType {
entryConfig["token_type"] = entry.Config.TokenType.String()
}
@ -859,6 +862,9 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
if len(apiConfig.PassthroughRequestHeaders) > 0 {
config.PassthroughRequestHeaders = apiConfig.PassthroughRequestHeaders
}
if len(apiConfig.AllowedResponseHeaders) > 0 {
config.AllowedResponseHeaders = apiConfig.AllowedResponseHeaders
}
// Create the mount entry
me := &MountEntry{
@ -1051,6 +1057,10 @@ func (b *SystemBackend) handleTuneReadCommon(ctx context.Context, path string) (
resp.Data["passthrough_request_headers"] = rawVal.([]string)
}
if rawVal, ok := mountEntry.synthesizedConfigCache.Load("allowed_response_headers"); ok {
resp.Data["allowed_response_headers"] = rawVal.([]string)
}
if len(mountEntry.Options) > 0 {
resp.Data["options"] = mountEntry.Options
}
@ -1334,6 +1344,32 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string,
}
}
if rawVal, ok := data.GetOk("allowed_response_headers"); ok {
headers := rawVal.([]string)
oldVal := mountEntry.Config.AllowedResponseHeaders
mountEntry.Config.AllowedResponseHeaders = headers
// Update the mount table
var err error
switch {
case strings.HasPrefix(path, "auth/"):
err = b.Core.persistAuth(ctx, b.Core.auth, &mountEntry.Local)
default:
err = b.Core.persistMounts(ctx, b.Core.mounts, &mountEntry.Local)
}
if err != nil {
mountEntry.Config.AllowedResponseHeaders = oldVal
return handleError(err)
}
mountEntry.SyncCache()
if b.Core.logger.IsInfo() {
b.Core.logger.Info("mount tuning of allowed_response_headers successful", "path", path)
}
}
var err error
var resp *logical.Response
var options map[string]string
@ -1737,6 +1773,9 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
if len(apiConfig.PassthroughRequestHeaders) > 0 {
config.PassthroughRequestHeaders = apiConfig.PassthroughRequestHeaders
}
if len(apiConfig.AllowedResponseHeaders) > 0 {
config.AllowedResponseHeaders = apiConfig.AllowedResponseHeaders
}
// Create the mount entry
me := &MountEntry{
@ -3816,7 +3855,11 @@ This path responds to the following HTTP methods.
"",
},
"passthrough_request_headers": {
"A list of headers to whitelist and pass from the request to the backend.",
"A list of headers to whitelist and pass from the request to the plugin.",
"",
},
"allowed_response_headers": {
"A list of headers to whitelist and allow a plugin to set on responses.",
"",
},
"token_type": {

View File

@ -1149,6 +1149,10 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"allowed_response_headers": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"token_type": &framework.FieldSchema{
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
@ -1439,6 +1443,10 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"allowed_response_headers": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"token_type": &framework.FieldSchema{
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),

View File

@ -227,6 +227,7 @@ type MountConfig struct {
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" structs:"passthrough_request_headers" mapstructure:"passthrough_request_headers"`
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" structs:"allowed_response_headers" mapstructure:"allowed_response_headers"`
TokenType logical.TokenType `json:"token_type" structs:"token_type" mapstructure:"token_type"`
// PluginName is the name of the plugin registered in the catalog.
@ -244,6 +245,7 @@ type APIMountConfig struct {
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" structs:"audit_non_hmac_response_keys" mapstructure:"audit_non_hmac_response_keys"`
ListingVisibility ListingVisibilityType `json:"listing_visibility,omitempty" structs:"listing_visibility" mapstructure:"listing_visibility"`
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" structs:"passthrough_request_headers" mapstructure:"passthrough_request_headers"`
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" structs:"allowed_response_headers" mapstructure:"allowed_response_headers"`
TokenType string `json:"token_type" structs:"token_type" mapstructure:"token_type"`
// PluginName is the name of the plugin registered in the catalog.
@ -296,6 +298,12 @@ func (e *MountEntry) SyncCache() {
} else {
e.synthesizedConfigCache.Store("passthrough_request_headers", e.Config.PassthroughRequestHeaders)
}
if len(e.Config.AllowedResponseHeaders) == 0 {
e.synthesizedConfigCache.Delete("allowed_response_headers")
} else {
e.synthesizedConfigCache.Store("allowed_response_headers", e.Config.AllowedResponseHeaders)
}
}
func (c *Core) decodeMountTable(ctx context.Context, raw []byte) (*MountTable, error) {

View File

@ -5,15 +5,11 @@ package vault
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
forwarding "github.com/hashicorp/vault/helper/forwarding"
)
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -322,6 +318,45 @@ func init() {
proto.RegisterType((*PerfStandbyElectionResponse)(nil), "vault.PerfStandbyElectionResponse")
}
func init() {
proto.RegisterFile("vault/request_forwarding_service.proto", fileDescriptor_f5f7512e4ab7b58a)
}
var fileDescriptor_f5f7512e4ab7b58a = []byte{
// 493 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x41, 0x6f, 0x1a, 0x3d,
0x10, 0x8d, 0x81, 0x10, 0x31, 0x90, 0x88, 0xf8, 0x8b, 0xf4, 0xad, 0xa8, 0xa2, 0x90, 0xad, 0x54,
0x21, 0x55, 0xda, 0x8d, 0xd2, 0x73, 0x0f, 0x2d, 0x4a, 0x25, 0xd4, 0x4b, 0xb5, 0xb9, 0xf5, 0xb2,
0x32, 0xf6, 0x04, 0xac, 0x2e, 0x6b, 0xd7, 0x36, 0x49, 0xf6, 0x27, 0xf7, 0xd6, 0x9f, 0x50, 0xad,
0xd7, 0x04, 0x10, 0x4d, 0x2f, 0x68, 0xe7, 0xcd, 0x63, 0xde, 0xf8, 0xf9, 0x19, 0xde, 0x3d, 0xb2,
0x75, 0xe1, 0x52, 0x83, 0x3f, 0xd7, 0x68, 0x5d, 0xfe, 0xa0, 0xcc, 0x13, 0x33, 0x42, 0x96, 0x8b,
0xdc, 0xa2, 0x79, 0x94, 0x1c, 0x13, 0x6d, 0x94, 0x53, 0xf4, 0xd8, 0xf3, 0x46, 0x97, 0x4b, 0x2c,
0x34, 0x9a, 0x74, 0xcb, 0x4b, 0x5d, 0xa5, 0xd1, 0x36, 0xac, 0x58, 0x41, 0xff, 0x8e, 0x2f, 0x55,
0xd6, 0x4c, 0xa3, 0x11, 0x9c, 0xac, 0xd0, 0x5a, 0xb6, 0xc0, 0x88, 0x8c, 0xc9, 0xa4, 0x97, 0x6d,
0x4a, 0x7a, 0x0d, 0x03, 0x5e, 0xac, 0xad, 0x43, 0x93, 0x33, 0x21, 0x4c, 0xd4, 0xf2, 0xed, 0x7e,
0xc0, 0x3e, 0x09, 0x61, 0xe8, 0x5b, 0x38, 0xdd, 0xa5, 0xd8, 0xa8, 0x3d, 0x6e, 0x4f, 0x7a, 0xd9,
0x60, 0x87, 0x63, 0xe3, 0x27, 0xe8, 0x35, 0x82, 0xba, 0xa8, 0xfe, 0x21, 0x77, 0x30, 0xab, 0x75,
0x38, 0x8b, 0xbe, 0x87, 0x73, 0x83, 0xba, 0x90, 0x9c, 0x39, 0xa9, 0xca, 0xdc, 0x3a, 0xe6, 0x30,
0x6a, 0x8f, 0xc9, 0xe4, 0x34, 0x1b, 0xee, 0x34, 0xee, 0x6b, 0x3c, 0x9e, 0x41, 0x6f, 0x5a, 0x48,
0x2c, 0xdd, 0x57, 0xac, 0x28, 0x85, 0x4e, 0xed, 0x42, 0x50, 0xf5, 0xdf, 0x74, 0x00, 0xe4, 0xd9,
0x1f, 0x6b, 0x90, 0x91, 0xe7, 0xba, 0xaa, 0xfc, 0xac, 0x41, 0x46, 0xaa, 0xba, 0x12, 0x51, 0xa7,
0xa9, 0x44, 0x3c, 0x82, 0xe8, 0x1b, 0x9a, 0x87, 0x7b, 0xc7, 0x4a, 0x31, 0xaf, 0xee, 0x0a, 0xe4,
0xb5, 0xcc, 0xac, 0xd4, 0x6b, 0x17, 0xff, 0x22, 0xf0, 0xe6, 0x2f, 0xcd, 0x0c, 0xad, 0x56, 0xa5,
0x45, 0x7a, 0x06, 0x2d, 0x29, 0x82, 0x6e, 0x4b, 0x0a, 0x7a, 0x09, 0xb0, 0x39, 0xa8, 0x14, 0xc1,
0xd5, 0x5e, 0x40, 0x66, 0x82, 0xde, 0xc0, 0x85, 0x36, 0x72, 0xc5, 0x4c, 0x95, 0xef, 0xd9, 0xdf,
0xf6, 0x44, 0x1a, 0x7a, 0xd3, 0x9d, 0x5b, 0xf8, 0x1f, 0x4e, 0x38, 0xcb, 0x39, 0x1a, 0x17, 0x16,
0xee, 0x72, 0x36, 0x45, 0xe3, 0xe8, 0x15, 0xf4, 0xb9, 0x37, 0xa0, 0x69, 0x1e, 0xfb, 0x26, 0x34,
0x90, 0x27, 0xa4, 0x10, 0xaa, 0xfc, 0x07, 0x56, 0x51, 0x77, 0x4c, 0x26, 0xfd, 0xdb, 0x61, 0xe2,
0x63, 0x94, 0xbc, 0x58, 0x57, 0x2f, 0x17, 0x3e, 0x6f, 0x7f, 0x13, 0x38, 0x0f, 0xc9, 0xf9, 0xf2,
0x12, 0x2f, 0xfa, 0x11, 0xce, 0x42, 0xb5, 0x49, 0xd5, 0x7f, 0xc9, 0x36, 0x7d, 0x49, 0x00, 0x47,
0x17, 0xfb, 0x60, 0x63, 0x4f, 0x7c, 0x44, 0x13, 0xe8, 0xd4, 0x01, 0xa1, 0x34, 0x28, 0xef, 0xc4,
0x73, 0x34, 0xdc, 0xc3, 0x74, 0x51, 0xc5, 0x47, 0xb4, 0x80, 0xeb, 0xda, 0x6f, 0x65, 0x56, 0xac,
0xe4, 0x78, 0x60, 0x7b, 0xb3, 0xc1, 0x55, 0xf8, 0xe3, 0x6b, 0xd7, 0x36, 0x8a, 0x5f, 0x27, 0x6c,
0x77, 0xbb, 0x21, 0x9f, 0xe3, 0xef, 0xe3, 0x85, 0x74, 0xcb, 0xf5, 0x3c, 0xe1, 0x6a, 0x95, 0x2e,
0x99, 0x5d, 0x4a, 0xae, 0x8c, 0x4e, 0x9b, 0x47, 0xe9, 0x7f, 0xe7, 0x5d, 0xff, 0xb4, 0x3e, 0xfc,
0x09, 0x00, 0x00, 0xff, 0xff, 0x03, 0x94, 0x0a, 0x17, 0xaa, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
@ -487,42 +522,3 @@ var _RequestForwarding_serviceDesc = grpc.ServiceDesc{
},
Metadata: "vault/request_forwarding_service.proto",
}
func init() {
proto.RegisterFile("vault/request_forwarding_service.proto", fileDescriptor_f5f7512e4ab7b58a)
}
var fileDescriptor_f5f7512e4ab7b58a = []byte{
// 493 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x41, 0x6f, 0x1a, 0x3d,
0x10, 0x8d, 0x81, 0x10, 0x31, 0x90, 0x88, 0xf8, 0x8b, 0xf4, 0xad, 0xa8, 0xa2, 0x90, 0xad, 0x54,
0x21, 0x55, 0xda, 0x8d, 0xd2, 0x73, 0x0f, 0x2d, 0x4a, 0x25, 0xd4, 0x4b, 0xb5, 0xb9, 0xf5, 0xb2,
0x32, 0xf6, 0x04, 0xac, 0x2e, 0x6b, 0xd7, 0x36, 0x49, 0xf6, 0x27, 0xf7, 0xd6, 0x9f, 0x50, 0xad,
0xd7, 0x04, 0x10, 0x4d, 0x2f, 0x68, 0xe7, 0xcd, 0x63, 0xde, 0xf8, 0xf9, 0x19, 0xde, 0x3d, 0xb2,
0x75, 0xe1, 0x52, 0x83, 0x3f, 0xd7, 0x68, 0x5d, 0xfe, 0xa0, 0xcc, 0x13, 0x33, 0x42, 0x96, 0x8b,
0xdc, 0xa2, 0x79, 0x94, 0x1c, 0x13, 0x6d, 0x94, 0x53, 0xf4, 0xd8, 0xf3, 0x46, 0x97, 0x4b, 0x2c,
0x34, 0x9a, 0x74, 0xcb, 0x4b, 0x5d, 0xa5, 0xd1, 0x36, 0xac, 0x58, 0x41, 0xff, 0x8e, 0x2f, 0x55,
0xd6, 0x4c, 0xa3, 0x11, 0x9c, 0xac, 0xd0, 0x5a, 0xb6, 0xc0, 0x88, 0x8c, 0xc9, 0xa4, 0x97, 0x6d,
0x4a, 0x7a, 0x0d, 0x03, 0x5e, 0xac, 0xad, 0x43, 0x93, 0x33, 0x21, 0x4c, 0xd4, 0xf2, 0xed, 0x7e,
0xc0, 0x3e, 0x09, 0x61, 0xe8, 0x5b, 0x38, 0xdd, 0xa5, 0xd8, 0xa8, 0x3d, 0x6e, 0x4f, 0x7a, 0xd9,
0x60, 0x87, 0x63, 0xe3, 0x27, 0xe8, 0x35, 0x82, 0xba, 0xa8, 0xfe, 0x21, 0x77, 0x30, 0xab, 0x75,
0x38, 0x8b, 0xbe, 0x87, 0x73, 0x83, 0xba, 0x90, 0x9c, 0x39, 0xa9, 0xca, 0xdc, 0x3a, 0xe6, 0x30,
0x6a, 0x8f, 0xc9, 0xe4, 0x34, 0x1b, 0xee, 0x34, 0xee, 0x6b, 0x3c, 0x9e, 0x41, 0x6f, 0x5a, 0x48,
0x2c, 0xdd, 0x57, 0xac, 0x28, 0x85, 0x4e, 0xed, 0x42, 0x50, 0xf5, 0xdf, 0x74, 0x00, 0xe4, 0xd9,
0x1f, 0x6b, 0x90, 0x91, 0xe7, 0xba, 0xaa, 0xfc, 0xac, 0x41, 0x46, 0xaa, 0xba, 0x12, 0x51, 0xa7,
0xa9, 0x44, 0x3c, 0x82, 0xe8, 0x1b, 0x9a, 0x87, 0x7b, 0xc7, 0x4a, 0x31, 0xaf, 0xee, 0x0a, 0xe4,
0xb5, 0xcc, 0xac, 0xd4, 0x6b, 0x17, 0xff, 0x22, 0xf0, 0xe6, 0x2f, 0xcd, 0x0c, 0xad, 0x56, 0xa5,
0x45, 0x7a, 0x06, 0x2d, 0x29, 0x82, 0x6e, 0x4b, 0x0a, 0x7a, 0x09, 0xb0, 0x39, 0xa8, 0x14, 0xc1,
0xd5, 0x5e, 0x40, 0x66, 0x82, 0xde, 0xc0, 0x85, 0x36, 0x72, 0xc5, 0x4c, 0x95, 0xef, 0xd9, 0xdf,
0xf6, 0x44, 0x1a, 0x7a, 0xd3, 0x9d, 0x5b, 0xf8, 0x1f, 0x4e, 0x38, 0xcb, 0x39, 0x1a, 0x17, 0x16,
0xee, 0x72, 0x36, 0x45, 0xe3, 0xe8, 0x15, 0xf4, 0xb9, 0x37, 0xa0, 0x69, 0x1e, 0xfb, 0x26, 0x34,
0x90, 0x27, 0xa4, 0x10, 0xaa, 0xfc, 0x07, 0x56, 0x51, 0x77, 0x4c, 0x26, 0xfd, 0xdb, 0x61, 0xe2,
0x63, 0x94, 0xbc, 0x58, 0x57, 0x2f, 0x17, 0x3e, 0x6f, 0x7f, 0x13, 0x38, 0x0f, 0xc9, 0xf9, 0xf2,
0x12, 0x2f, 0xfa, 0x11, 0xce, 0x42, 0xb5, 0x49, 0xd5, 0x7f, 0xc9, 0x36, 0x7d, 0x49, 0x00, 0x47,
0x17, 0xfb, 0x60, 0x63, 0x4f, 0x7c, 0x44, 0x13, 0xe8, 0xd4, 0x01, 0xa1, 0x34, 0x28, 0xef, 0xc4,
0x73, 0x34, 0xdc, 0xc3, 0x74, 0x51, 0xc5, 0x47, 0xb4, 0x80, 0xeb, 0xda, 0x6f, 0x65, 0x56, 0xac,
0xe4, 0x78, 0x60, 0x7b, 0xb3, 0xc1, 0x55, 0xf8, 0xe3, 0x6b, 0xd7, 0x36, 0x8a, 0x5f, 0x27, 0x6c,
0x77, 0xbb, 0x21, 0x9f, 0xe3, 0xef, 0xe3, 0x85, 0x74, 0xcb, 0xf5, 0x3c, 0xe1, 0x6a, 0x95, 0x2e,
0x99, 0x5d, 0x4a, 0xae, 0x8c, 0x4e, 0x9b, 0x47, 0xe9, 0x7f, 0xe7, 0x5d, 0xff, 0xb4, 0x3e, 0xfc,
0x09, 0x00, 0x00, 0xff, 0xff, 0x03, 0x94, 0x0a, 0x17, 0xaa, 0x03, 0x00, 0x00,
}

View File

@ -18,8 +18,7 @@ import (
)
var (
denylistHeaders = []string{
"Authorization",
deniedPassthroughRequestHeaders = []string{
consts.AuthHeaderName,
}
)
@ -593,13 +592,21 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
// Cache the headers
headers := req.Headers
req.Headers = nil
// Filter and add passthrough headers to the backend
var passthroughRequestHeaders []string
if rawVal, ok := re.mountEntry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
passthroughRequestHeaders = rawVal.([]string)
}
req.Headers = filteredPassthroughHeaders(headers, passthroughRequestHeaders)
var allowedResponseHeaders []string
if rawVal, ok := re.mountEntry.synthesizedConfigCache.Load("allowed_response_headers"); ok {
allowedResponseHeaders = rawVal.([]string)
}
if len(passthroughRequestHeaders) > 0 {
req.Headers = filteredHeaders(headers, passthroughRequestHeaders, deniedPassthroughRequestHeaders)
}
// Cache the wrap info of the request
var wrapInfo *logical.RequestWrapInfo
@ -650,43 +657,50 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
return nil, ok, exists, err
} else {
resp, err := re.backend.HandleRequest(ctx, req)
if resp != nil &&
resp.Auth != nil {
// When a token gets renewed, the request hits this path and
// reaches token store. Token store delegates the renewal to the
// expiration manager. Expiration manager in-turn creates a
// different logical request and forwards the request to the auth
// backend that had initially authenticated the login request. The
// forwarding to auth backend will make this code path hit for the
// second time for the same renewal request. The accessors in the
// Alias structs should be of the auth backend and not of the token
// store. Therefore, avoiding the overwriting of accessors by
// having a check for path prefix having "renew". This gets applied
// for "renew" and "renew-self" requests.
if !strings.HasPrefix(req.Path, "renew") {
if resp.Auth.Alias != nil {
resp.Auth.Alias.MountAccessor = re.mountEntry.Accessor
}
for _, alias := range resp.Auth.GroupAliases {
alias.MountAccessor = re.mountEntry.Accessor
}
if resp != nil {
if len(allowedResponseHeaders) > 0 {
resp.Headers = filteredHeaders(resp.Headers, allowedResponseHeaders, nil)
} else {
resp.Headers = nil
}
switch re.mountEntry.Type {
case "token", "ns_token":
// Nothing; we respect what the token store is telling us and
// we don't allow tuning
default:
switch re.mountEntry.Config.TokenType {
case logical.TokenTypeService, logical.TokenTypeBatch:
resp.Auth.TokenType = re.mountEntry.Config.TokenType
case logical.TokenTypeDefault, logical.TokenTypeDefaultService:
if resp.Auth.TokenType == logical.TokenTypeDefault {
resp.Auth.TokenType = logical.TokenTypeService
if resp.Auth != nil {
// When a token gets renewed, the request hits this path and
// reaches token store. Token store delegates the renewal to the
// expiration manager. Expiration manager in-turn creates a
// different logical request and forwards the request to the auth
// backend that had initially authenticated the login request. The
// forwarding to auth backend will make this code path hit for the
// second time for the same renewal request. The accessors in the
// Alias structs should be of the auth backend and not of the token
// store. Therefore, avoiding the overwriting of accessors by
// having a check for path prefix having "renew". This gets applied
// for "renew" and "renew-self" requests.
if !strings.HasPrefix(req.Path, "renew") {
if resp.Auth.Alias != nil {
resp.Auth.Alias.MountAccessor = re.mountEntry.Accessor
}
case logical.TokenTypeDefaultBatch:
if resp.Auth.TokenType == logical.TokenTypeDefault {
resp.Auth.TokenType = logical.TokenTypeBatch
for _, alias := range resp.Auth.GroupAliases {
alias.MountAccessor = re.mountEntry.Accessor
}
}
switch re.mountEntry.Type {
case "token", "ns_token":
// Nothing; we respect what the token store is telling us and
// we don't allow tuning
default:
switch re.mountEntry.Config.TokenType {
case logical.TokenTypeService, logical.TokenTypeBatch:
resp.Auth.TokenType = re.mountEntry.Config.TokenType
case logical.TokenTypeDefault, logical.TokenTypeDefaultService:
if resp.Auth.TokenType == logical.TokenTypeDefault {
resp.Auth.TokenType = logical.TokenTypeService
}
case logical.TokenTypeDefaultBatch:
if resp.Auth.TokenType == logical.TokenTypeDefault {
resp.Auth.TokenType = logical.TokenTypeBatch
}
}
}
}
@ -787,34 +801,35 @@ func pathsToRadix(paths []string) *radix.Tree {
return tree
}
// filteredPassthroughHeaders returns a headers map[string][]string that
// contains the filtered values contained in passthroughHeaders. Filtering of
// passthroughHeaders from the origHeaders is done is a case-insensitive manner.
// Headers that match values from denylistHeaders will be ignored.
func filteredPassthroughHeaders(origHeaders map[string][]string, passthroughHeaders []string) map[string][]string {
retHeaders := make(map[string][]string)
// filteredHeaders returns a headers map[string][]string that
// contains the filtered values contained in candidateHeaders. Filtering of
// candidateHeaders from the origHeaders is done is a case-insensitive manner.
// Headers that match values from deniedHeaders will be ignored.
func filteredHeaders(origHeaders map[string][]string, candidateHeaders, deniedHeaders []string) map[string][]string {
// Short-circuit if there's nothing to filter
if len(passthroughHeaders) == 0 {
return retHeaders
if len(candidateHeaders) == 0 {
return nil
}
// Filter passthroughHeaders values through denyListHeaders first. Returns the
// lowercased the complement set.
passthroughHeadersSubset := strutil.Difference(passthroughHeaders, denylistHeaders, true)
retHeaders := make(map[string][]string, len(origHeaders))
// Filter candidateHeaders values through deniedHeaders first. Returns the
// lowercased complement set. We call even if no denied headers to get the
// values lowercased.
allowedCandidateHeaders := strutil.Difference(candidateHeaders, deniedHeaders, true)
// Create a map that uses lowercased header values as the key and the original
// header naming as the value for comparison down below.
lowerHeadersRef := make(map[string]string, len(origHeaders))
lowerOrigHeaderKeys := make(map[string]string, len(origHeaders))
for key := range origHeaders {
lowerHeadersRef[strings.ToLower(key)] = key
lowerOrigHeaderKeys[strings.ToLower(key)] = key
}
// Case-insensitive compare of passthrough headers against originating
// headers. The returned headers will be the same casing as the originating
// header name.
for _, ph := range passthroughHeadersSubset {
if header, ok := lowerHeadersRef[ph]; ok {
for _, ch := range allowedCandidateHeaders {
if header, ok := lowerOrigHeaderKeys[ch]; ok {
retHeaders[header] = origHeaders[header]
}
}

View File

@ -81,22 +81,25 @@ For example, enable the "foo" auth method will make it accessible at
this auth method. These are the possible values:
- `default_lease_ttl` `(string: "")` - The default lease duration, specified
as a string duration like "5s" or "30m".
as a string duration like "5s" or "30m".
- `max_lease_ttl` `(string: "")` - The maximum lease duration, specified as a
string duration like "5s" or "30m".
string duration like "5s" or "30m".
- `audit_non_hmac_request_keys` `(array: [])` - Comma-separated list of keys
that will not be HMAC'd by audit devices in the request data object.
that will not be HMAC'd by audit devices in the request data object.
- `audit_non_hmac_response_keys` `(array: [])` - Comma-separated list of keys
that will not be HMAC'd by audit devices in the response data object.
that will not be HMAC'd by audit devices in the response data object.
- `listing_visibility` `(string: "")` - Specifies whether to show this mount
in the UI-specific listing endpoint.
in the UI-specific listing endpoint.
- `passthrough_request_headers` `(array: [])` - Comma-separated list of headers
to whitelist and pass from the request to the backend.
to whitelist and pass from the request to the plugin.
- `allowed_response_headers` `(array: [])` - Comma-separated list of headers
to whitelist, allowing a plugin to include them in the response.
Additionally, the following options are allowed in Vault open-source, but
relevant functionality is only supported in Vault Enterprise:
@ -110,6 +113,9 @@ relevant functionality is only supported in Vault Enterprise:
primary if a request is forwarded. Never give untrusted administrators the
ability to assign policies or configure authentication methods.
- `seal_wrap` `(bool: false)` - Enable seal wrapping for the mount, causing
values stored by the mount to be wrapped by the seal's encryption capability.
### Sample Payload
```json
@ -221,10 +227,13 @@ can be achieved without `sudo` via `sys/mounts/auth/[auth-path]/tune`._
object.
- `listing_visibility` `(string: "")` - Specifies whether to show this mount
in the UI-specific listing endpoint. Valid values are `"unauth"` or `""`.
in the UI-specific listing endpoint. Valid values are `"unauth"` or `""`.
- `passthrough_request_headers` `(array: [])` - Comma-separated list of headers
to whitelist and pass from the request to the backend.
to whitelist and pass from the request to the plugin.
- `allowed_response_headers` `(array: [])` - Comma-separated list of headers
to whitelist, allowing a plugin to include them in the response.
- `token_type` `(string: "")` Specifies the type of tokens that should be
returned by the mount. The following values are available:

View File

@ -79,42 +79,37 @@ This endpoint enables a new secrets engine at the given path.
mount.
- `config` `(map<string|string>: nil)`  Specifies configuration options for
this mount. This is an object with four possible values:
this mount; if set on a specific mount, values will override any global
defaults (e.g. the system TTL/Max TTL)
- `default_lease_ttl` `(string: "")` - The default lease duration, specified
as a string duration like "5s" or "30m".
as a string duration like "5s" or "30m".
- `max_lease_ttl` `(string: "")` - The maximum lease duration, specified as a
string duration like "5s" or "30m".
string duration like "5s" or "30m".
- `force_no_cache` `(bool: false)` - Disable caching.
- `audit_non_hmac_request_keys` `(array: [])` - Comma-separated list of keys
that will not be HMAC'd by audit devices in the request data object.
that will not be HMAC'd by audit devices in the request data object.
- `audit_non_hmac_response_keys` `(array: [])` - Comma-separated list of keys
that will not be HMAC'd by audit devices in the response data object.
that will not be HMAC'd by audit devices in the response data object.
- `listing_visibility` `(string: "")` - Specifies whether to show this mount
in the UI-specific listing endpoint. Valid values are `"unauth"` or
`"hidden"`. If not set, behaves like `"hidden"`.
- `passthrough_request_headers` `(array: [])` - Comma-separated list of headers
to whitelist and pass from the request to the backend.
to whitelist and pass from the request to the plugin.
These control the default and maximum lease time-to-live, and the force
disabling backend caching. They override the global defaults if
set on a specific mount.
- `allowed_response_headers` `(array: [])` - Comma-separated list of headers
to whitelist, allowing a plugin to include them in the response.
When used with supported seals (`pkcs11`, `awskms`, etc.), `seal_wrap`
causes key material for supporting mounts to be wrapped by the seal's
encryption capability. This is currently only supported for `transit` and
`pki` backends. This is only available in Vault Enterprise.
- `options` `(map<string|string>: nil)` - Specifies mount type specific options
that are passed to the backend.
- `options` `(map<string|string>: nil)` - Specifies mount type specific options
that are passed to the backend.
*Key/Value (KV)*
*Key/Value (KV)*
- `version` `(string: "1")` - The version of the KV to mount. Set to "2" for mount
KV v2.
@ -125,7 +120,8 @@ relevant functionality is only supported in Vault Enterprise:
only. Local mounts are not replicated nor (if a secondary) removed by
replication.
- `seal_wrap` `(bool: false)` - Enable seal wrapping for the mount.
- `seal_wrap` `(bool: false)` - Enable seal wrapping for the mount, causing
values stored by the mount to be wrapped by the seal's encryption capability.
### Sample Payload
@ -227,7 +223,10 @@ This endpoint tunes configuration parameters for a given mount point.
If not set, behaves like `"hidden"`.
- `passthrough_request_headers` `(array: [])` - Comma-separated list of headers
to whitelist and pass from the request to the backend.
to whitelist and pass from the request to the plugin.
- `allowed_response_headers` `(array: [])` - Comma-separated list of headers
to whitelist, allowing a plugin to include them in the response.
### Sample Payload