feat(worker): Implement egress credentials

Egress credentials Issued during AuthorizeSession are stored in the
session repo. These credentials are retrieved and stored in-memory on the
worker during the LookupSession call. Each proxy handler will need to
handle the credentials as required.
pull/1804/head
Louis Ruch 4 years ago
parent 5fe23ab14d
commit 425a56179f

@ -0,0 +1,253 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// source: controller/servers/services/v1/credential.proto
package services
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Credential struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Types that are assignable to Credential:
// *Credential_UserPassword
Credential isCredential_Credential `protobuf_oneof:"credential"`
}
func (x *Credential) Reset() {
*x = Credential{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_servers_services_v1_credential_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Credential) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Credential) ProtoMessage() {}
func (x *Credential) ProtoReflect() protoreflect.Message {
mi := &file_controller_servers_services_v1_credential_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Credential.ProtoReflect.Descriptor instead.
func (*Credential) Descriptor() ([]byte, []int) {
return file_controller_servers_services_v1_credential_proto_rawDescGZIP(), []int{0}
}
func (m *Credential) GetCredential() isCredential_Credential {
if m != nil {
return m.Credential
}
return nil
}
func (x *Credential) GetUserPassword() *UserPassword {
if x, ok := x.GetCredential().(*Credential_UserPassword); ok {
return x.UserPassword
}
return nil
}
type isCredential_Credential interface {
isCredential_Credential()
}
type Credential_UserPassword struct {
UserPassword *UserPassword `protobuf:"bytes,1,opt,name=user_password,json=userPassword,proto3,oneof"`
}
func (*Credential_UserPassword) isCredential_Credential() {}
// UserPassword is a credential containing a username and a password.
type UserPassword struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The username of the credential
Username string `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty"` // @gotags: `class:"public"`
// The password of the credential
Password string `protobuf:"bytes,20,opt,name=password,proto3" json:"password,omitempty"` // @gotags: `class:"secret"`
}
func (x *UserPassword) Reset() {
*x = UserPassword{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_servers_services_v1_credential_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UserPassword) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserPassword) ProtoMessage() {}
func (x *UserPassword) ProtoReflect() protoreflect.Message {
mi := &file_controller_servers_services_v1_credential_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserPassword.ProtoReflect.Descriptor instead.
func (*UserPassword) Descriptor() ([]byte, []int) {
return file_controller_servers_services_v1_credential_proto_rawDescGZIP(), []int{1}
}
func (x *UserPassword) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *UserPassword) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
var File_controller_servers_services_v1_credential_proto protoreflect.FileDescriptor
var file_controller_servers_services_v1_credential_proto_rawDesc = []byte{
0x0a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31,
0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x1e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x22, 0x6f, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12,
0x53, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x48, 0x00, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x22, 0x46, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a,
0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_controller_servers_services_v1_credential_proto_rawDescOnce sync.Once
file_controller_servers_services_v1_credential_proto_rawDescData = file_controller_servers_services_v1_credential_proto_rawDesc
)
func file_controller_servers_services_v1_credential_proto_rawDescGZIP() []byte {
file_controller_servers_services_v1_credential_proto_rawDescOnce.Do(func() {
file_controller_servers_services_v1_credential_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_servers_services_v1_credential_proto_rawDescData)
})
return file_controller_servers_services_v1_credential_proto_rawDescData
}
var file_controller_servers_services_v1_credential_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_controller_servers_services_v1_credential_proto_goTypes = []interface{}{
(*Credential)(nil), // 0: controller.servers.services.v1.Credential
(*UserPassword)(nil), // 1: controller.servers.services.v1.UserPassword
}
var file_controller_servers_services_v1_credential_proto_depIdxs = []int32{
1, // 0: controller.servers.services.v1.Credential.user_password:type_name -> controller.servers.services.v1.UserPassword
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_controller_servers_services_v1_credential_proto_init() }
func file_controller_servers_services_v1_credential_proto_init() {
if File_controller_servers_services_v1_credential_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_controller_servers_services_v1_credential_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Credential); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_servers_services_v1_credential_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserPassword); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_controller_servers_services_v1_credential_proto_msgTypes[0].OneofWrappers = []interface{}{
(*Credential_UserPassword)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_servers_services_v1_credential_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_controller_servers_services_v1_credential_proto_goTypes,
DependencyIndexes: file_controller_servers_services_v1_credential_proto_depIdxs,
MessageInfos: file_controller_servers_services_v1_credential_proto_msgTypes,
}.Build()
File_controller_servers_services_v1_credential_proto = out.File
file_controller_servers_services_v1_credential_proto_rawDesc = nil
file_controller_servers_services_v1_credential_proto_goTypes = nil
file_controller_servers_services_v1_credential_proto_depIdxs = nil
}

@ -99,6 +99,7 @@ type LookupSessionResponse struct {
HostSetId string `protobuf:"bytes,100,opt,name=host_set_id,json=hostSetId,proto3" json:"host_set_id,omitempty" class:"public"` // @gotags: `class:"public"`
TargetId string `protobuf:"bytes,110,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty" class:"public"` // @gotags: `class:"public"`
UserId string `protobuf:"bytes,120,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty" class:"public"` // @gotags: `class:"public"`
Credentials []*Credential `protobuf:"bytes,130,rep,name=credentials,proto3" json:"credentials,omitempty" class:"secret"` // @gotags: `class:"secret"`
}
func (x *LookupSessionResponse) Reset() {
@ -217,6 +218,13 @@ func (x *LookupSessionResponse) GetUserId() string {
return ""
}
func (x *LookupSessionResponse) GetCredentials() []*Credential {
if x != nil {
return x.Credentials
}
return nil
}
type ActivateSessionRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -566,8 +574,8 @@ type ConnectConnectionRequest struct {
EndpointTcpAddress string `protobuf:"bytes,40,opt,name=endpoint_tcp_address,json=endpointTcpAddress,proto3" json:"endpoint_tcp_address,omitempty" class:"public"` // @gotags: `class:"public"`
EndpointTcpPort uint32 `protobuf:"varint,50,opt,name=endpoint_tcp_port,json=endpointTcpPort,proto3" json:"endpoint_tcp_port,omitempty" class:"public"` // @gotags: `class:"public"`
Type string `protobuf:"bytes,60,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"`
// user_client_ip is the user's client ip for the connection as determined
// the inbound http request
// user_client_ip is the user's client ip for the connection as determined by
// the inbound http request handler
UserClientIp string `protobuf:"bytes,70,opt,name=user_client_ip,json=userClientIp,proto3" json:"user_client_ip,omitempty" class:"public"` // @gotags: `class:"public"
}
@ -932,50 +940,58 @@ var file_controller_servers_services_v1_session_service_proto_rawDesc = []byte{
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x40, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x67, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x52, 0x0a, 0x14, 0x4c,
0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18,
0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64, 0x22,
0x99, 0x04, 0x0a, 0x15, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x75, 0x74,
0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52,
0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d,
0x0a, 0x0a, 0x74, 0x6f, 0x66, 0x75, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x14, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x66, 0x75, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x45, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x52, 0x06,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x46, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x6d, 0x69,
0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x5f, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x50, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x17, 0x0a, 0x07,
0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68,
0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65,
0x74, 0x5f, 0x69, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74,
0x53, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
0x69, 0x64, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x78, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x16,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x40, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x52, 0x0a, 0x14,
0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64,
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49, 0x64,
0x22, 0xe8, 0x04, 0x0a, 0x15, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69,
0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61,
0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x66, 0x75, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x14, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x66, 0x75, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18,
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x45, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x52,
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x46, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x6d,
0x69, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x50, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x17, 0x0a,
0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73,
0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73,
0x74, 0x53, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x5f, 0x69, 0x64, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x78,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b,
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x82, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0b,
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x22, 0xd4, 0x01, 0x0a, 0x16,
0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73,
@ -1174,37 +1190,39 @@ var file_controller_servers_services_v1_session_service_proto_goTypes = []interf
(*targets.SessionAuthorizationData)(nil), // 14: controller.api.resources.targets.v1.SessionAuthorizationData
(*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
(SESSIONSTATUS)(0), // 16: controller.servers.services.v1.SESSIONSTATUS
(CONNECTIONSTATUS)(0), // 17: controller.servers.services.v1.CONNECTIONSTATUS
(*Credential)(nil), // 17: controller.servers.services.v1.Credential
(CONNECTIONSTATUS)(0), // 18: controller.servers.services.v1.CONNECTIONSTATUS
}
var file_controller_servers_services_v1_session_service_proto_depIdxs = []int32{
14, // 0: controller.servers.services.v1.LookupSessionResponse.authorization:type_name -> controller.api.resources.targets.v1.SessionAuthorizationData
15, // 1: controller.servers.services.v1.LookupSessionResponse.expiration:type_name -> google.protobuf.Timestamp
16, // 2: controller.servers.services.v1.LookupSessionResponse.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
16, // 3: controller.servers.services.v1.ActivateSessionRequest.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
16, // 4: controller.servers.services.v1.ActivateSessionResponse.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
16, // 5: controller.servers.services.v1.CancelSessionResponse.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
17, // 6: controller.servers.services.v1.AuthorizeConnectionResponse.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
17, // 7: controller.servers.services.v1.ConnectConnectionResponse.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
10, // 8: controller.servers.services.v1.CloseConnectionRequest.close_request_data:type_name -> controller.servers.services.v1.CloseConnectionRequestData
17, // 9: controller.servers.services.v1.CloseConnectionResponseData.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
12, // 10: controller.servers.services.v1.CloseConnectionResponse.close_response_data:type_name -> controller.servers.services.v1.CloseConnectionResponseData
0, // 11: controller.servers.services.v1.SessionService.LookupSession:input_type -> controller.servers.services.v1.LookupSessionRequest
2, // 12: controller.servers.services.v1.SessionService.ActivateSession:input_type -> controller.servers.services.v1.ActivateSessionRequest
4, // 13: controller.servers.services.v1.SessionService.CancelSession:input_type -> controller.servers.services.v1.CancelSessionRequest
6, // 14: controller.servers.services.v1.SessionService.AuthorizeConnection:input_type -> controller.servers.services.v1.AuthorizeConnectionRequest
8, // 15: controller.servers.services.v1.SessionService.ConnectConnection:input_type -> controller.servers.services.v1.ConnectConnectionRequest
11, // 16: controller.servers.services.v1.SessionService.CloseConnection:input_type -> controller.servers.services.v1.CloseConnectionRequest
1, // 17: controller.servers.services.v1.SessionService.LookupSession:output_type -> controller.servers.services.v1.LookupSessionResponse
3, // 18: controller.servers.services.v1.SessionService.ActivateSession:output_type -> controller.servers.services.v1.ActivateSessionResponse
5, // 19: controller.servers.services.v1.SessionService.CancelSession:output_type -> controller.servers.services.v1.CancelSessionResponse
7, // 20: controller.servers.services.v1.SessionService.AuthorizeConnection:output_type -> controller.servers.services.v1.AuthorizeConnectionResponse
9, // 21: controller.servers.services.v1.SessionService.ConnectConnection:output_type -> controller.servers.services.v1.ConnectConnectionResponse
13, // 22: controller.servers.services.v1.SessionService.CloseConnection:output_type -> controller.servers.services.v1.CloseConnectionResponse
17, // [17:23] is the sub-list for method output_type
11, // [11:17] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
17, // 3: controller.servers.services.v1.LookupSessionResponse.credentials:type_name -> controller.servers.services.v1.Credential
16, // 4: controller.servers.services.v1.ActivateSessionRequest.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
16, // 5: controller.servers.services.v1.ActivateSessionResponse.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
16, // 6: controller.servers.services.v1.CancelSessionResponse.status:type_name -> controller.servers.services.v1.SESSIONSTATUS
18, // 7: controller.servers.services.v1.AuthorizeConnectionResponse.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
18, // 8: controller.servers.services.v1.ConnectConnectionResponse.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
10, // 9: controller.servers.services.v1.CloseConnectionRequest.close_request_data:type_name -> controller.servers.services.v1.CloseConnectionRequestData
18, // 10: controller.servers.services.v1.CloseConnectionResponseData.status:type_name -> controller.servers.services.v1.CONNECTIONSTATUS
12, // 11: controller.servers.services.v1.CloseConnectionResponse.close_response_data:type_name -> controller.servers.services.v1.CloseConnectionResponseData
0, // 12: controller.servers.services.v1.SessionService.LookupSession:input_type -> controller.servers.services.v1.LookupSessionRequest
2, // 13: controller.servers.services.v1.SessionService.ActivateSession:input_type -> controller.servers.services.v1.ActivateSessionRequest
4, // 14: controller.servers.services.v1.SessionService.CancelSession:input_type -> controller.servers.services.v1.CancelSessionRequest
6, // 15: controller.servers.services.v1.SessionService.AuthorizeConnection:input_type -> controller.servers.services.v1.AuthorizeConnectionRequest
8, // 16: controller.servers.services.v1.SessionService.ConnectConnection:input_type -> controller.servers.services.v1.ConnectConnectionRequest
11, // 17: controller.servers.services.v1.SessionService.CloseConnection:input_type -> controller.servers.services.v1.CloseConnectionRequest
1, // 18: controller.servers.services.v1.SessionService.LookupSession:output_type -> controller.servers.services.v1.LookupSessionResponse
3, // 19: controller.servers.services.v1.SessionService.ActivateSession:output_type -> controller.servers.services.v1.ActivateSessionResponse
5, // 20: controller.servers.services.v1.SessionService.CancelSession:output_type -> controller.servers.services.v1.CancelSessionResponse
7, // 21: controller.servers.services.v1.SessionService.AuthorizeConnection:output_type -> controller.servers.services.v1.AuthorizeConnectionResponse
9, // 22: controller.servers.services.v1.SessionService.ConnectConnection:output_type -> controller.servers.services.v1.ConnectConnectionResponse
13, // 23: controller.servers.services.v1.SessionService.CloseConnection:output_type -> controller.servers.services.v1.CloseConnectionResponse
18, // [18:24] is the sub-list for method output_type
12, // [12:18] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_controller_servers_services_v1_session_service_proto_init() }
@ -1212,6 +1230,7 @@ func file_controller_servers_services_v1_session_service_proto_init() {
if File_controller_servers_services_v1_session_service_proto != nil {
return
}
file_controller_servers_services_v1_credential_proto_init()
file_controller_servers_services_v1_server_coordination_service_proto_init()
if !protoimpl.UnsafeEnabled {
file_controller_servers_services_v1_session_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {

@ -18,7 +18,7 @@ const _ = grpc.SupportPackageIsVersion7
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type SessionServiceClient interface {
// GetSession allows a worker to retrieve session information from the
// LookupSession allows a worker to retrieve session information from the
// controller.
LookupSession(ctx context.Context, in *LookupSessionRequest, opts ...grpc.CallOption) (*LookupSessionResponse, error)
// ActivateSession allows a worker to activate a session on a controller.
@ -99,7 +99,7 @@ func (c *sessionServiceClient) CloseConnection(ctx context.Context, in *CloseCon
// All implementations must embed UnimplementedSessionServiceServer
// for forward compatibility
type SessionServiceServer interface {
// GetSession allows a worker to retrieve session information from the
// LookupSession allows a worker to retrieve session information from the
// controller.
LookupSession(context.Context, *LookupSessionRequest) (*LookupSessionResponse, error)
// ActivateSession allows a worker to activate a session on a controller.

@ -0,0 +1,20 @@
syntax = "proto3";
package controller.servers.services.v1;
option go_package = "github.com/hashicorp/boundary/internal/gen/controller/servers/services;services";
message Credential {
oneof credential {
UserPassword user_password = 1;
}
}
// UserPassword is a credential containing a username and a password.
message UserPassword {
// The username of the credential
string username = 10; // @gotags: `class:"public"`
// The password of the credential
string password = 20; // @gotags: `class:"secret"`
}

@ -6,10 +6,11 @@ option go_package = "github.com/hashicorp/boundary/internal/gen/controller/serve
import "google/protobuf/timestamp.proto";
import "controller/api/resources/targets/v1/target.proto";
import "controller/servers/services/v1/credential.proto";
import "controller/servers/services/v1/server_coordination_service.proto";
service SessionService {
// GetSession allows a worker to retrieve session information from the
// LookupSession allows a worker to retrieve session information from the
// controller.
rpc LookupSession(LookupSessionRequest) returns (LookupSessionResponse) {}
@ -52,6 +53,7 @@ message LookupSessionResponse {
string host_set_id = 100; // @gotags: `class:"public"`
string target_id = 110; // @gotags: `class:"public"`
string user_id = 120; // @gotags: `class:"public"`
repeated Credential credentials = 130; // @gotags: `class:"secret"`
}
message ActivateSessionRequest {

@ -16,6 +16,7 @@ import (
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/boundary/internal/errors"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
"github.com/hashicorp/boundary/internal/host"
"github.com/hashicorp/boundary/internal/host/plugin"
"github.com/hashicorp/boundary/internal/host/static"
@ -1063,52 +1064,78 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
}
var creds []*pb.SessionCredential
var workerCreds []session.Credential
for _, c := range cs {
l := c.Library()
secret := c.Secret()
// TODO: Access the json directly from the vault response instead of re-marshalling it.
jSecret, err := json.Marshal(secret)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to json"))
}
var sSecret *structpb.Struct
switch secret.(type) {
case map[string]interface{}:
// In this case we actually have to re-decode it. The proto wrappers
// choke on json.Number and at the time I'm writing this I don't
// have time to write a walk function to dig through with reflect
// and find all json.Numbers and replace them. So we eat the
// inefficiency. So note that we are specifically _not_ using a
// decoder with UseNumber here.
var dSecret map[string]interface{}
if err := json.Unmarshal(jSecret, &dSecret); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("decoding json for proto marshaling"))
switch c.Purpose() {
case credential.EgressPurpose:
m, err := credentialToProto(ctx, c)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
sSecret, err = structpb.NewStruct(dSecret)
data, err := proto.Marshal(m)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for secret"))
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to proto"))
}
workerCreds = append(workerCreds, data)
case credential.ApplicationPurpose:
l := c.Library()
secret := c.Secret()
// TODO: Access the json directly from the vault response instead of re-marshalling it.
jSecret, err := json.Marshal(secret)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("marshalling secret to json"))
}
var sSecret *structpb.Struct
switch secret.(type) {
case map[string]interface{}:
// In this case we actually have to re-decode it. The proto wrappers
// choke on json.Number and at the time I'm writing this I don't
// have time to write a walk function to dig through with reflect
// and find all json.Numbers and replace them. So we eat the
// inefficiency. So note that we are specifically _not_ using a
// decoder with UseNumber here.
var dSecret map[string]interface{}
if err := json.Unmarshal(jSecret, &dSecret); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("decoding json for proto marshaling"))
}
sSecret, err = structpb.NewStruct(dSecret)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating proto struct for secret"))
}
}
creds = append(creds, &pb.SessionCredential{
CredentialLibrary: &pb.CredentialLibrary{
Id: l.GetPublicId(),
Name: l.GetName(),
Description: l.GetDescription(),
CredentialStoreId: l.GetStoreId(),
Type: credential.SubtypeFromId(l.GetPublicId()).String(),
},
CredentialSource: &pb.CredentialSource{
Id: l.GetPublicId(),
Name: l.GetName(),
Description: l.GetDescription(),
CredentialStoreId: l.GetStoreId(),
Type: credential.SubtypeFromId(l.GetPublicId()).String(),
},
Secret: &pb.SessionSecret{
Raw: base64.StdEncoding.EncodeToString(jSecret),
Decoded: sSecret,
},
})
default:
return nil, errors.New(ctx, errors.Unknown, op, fmt.Sprintf("unsupported credential purpose %s", c.Purpose()))
}
}
if len(workerCreds) > 0 {
// store credentials in repo, worker will request creds when a connection is established
err = sessionRepo.AddSessionCredentials(ctx, sess.ScopeId, sess.PublicId, workerCreds)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
creds = append(creds, &pb.SessionCredential{
CredentialLibrary: &pb.CredentialLibrary{
Id: l.GetPublicId(),
Name: l.GetName(),
Description: l.GetDescription(),
CredentialStoreId: l.GetStoreId(),
Type: credential.SubtypeFromId(l.GetPublicId()).String(),
},
CredentialSource: &pb.CredentialSource{
Id: l.GetPublicId(),
Name: l.GetName(),
Description: l.GetDescription(),
CredentialStoreId: l.GetStoreId(),
Type: credential.SubtypeFromId(l.GetPublicId()).String(),
},
Secret: &pb.SessionSecret{
Raw: base64.StdEncoding.EncodeToString(jSecret),
Decoded: sSecret,
},
})
}
sad := &pb.SessionAuthorizationData{
@ -2079,3 +2106,22 @@ func createCredLibs(targetId string, applicationIds, ingressIds, egressIds []str
}
return credLibs, nil
}
// credentialToProto converts the strongly typed credential.Credential into a known proto.Message.
func credentialToProto(ctx context.Context, cred credential.Credential) (*serverpb.Credential, error) {
const op = "targets.credentialToProto"
switch c := cred.(type) {
case credential.UserPassword:
return &serverpb.Credential{
Credential: &serverpb.Credential_UserPassword{
UserPassword: &serverpb.UserPassword{
Username: c.Username(),
Password: string(c.Password()),
},
},
}, nil
default:
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported credential %T", c))
}
}

@ -19,6 +19,7 @@ import (
"github.com/hashicorp/go-bexpr"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
type workerServiceServer struct {
@ -277,6 +278,22 @@ func (ws *workerServiceServer) LookupSession(ctx context.Context, req *pbs.Looku
}
}
creds, err := sessRepo.ListSessionCredentials(ctx, sessionInfo.ScopeId, sessionInfo.PublicId)
if err != nil {
return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal,
fmt.Sprintf("Error retrieving session credentials: %s", err))
}
var workerCreds []*pbs.Credential
for _, c := range creds {
m := &pbs.Credential{}
err = proto.Unmarshal(c, m)
if err != nil {
return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal,
fmt.Sprintf("Error unmarshaling credentials: %s", err))
}
workerCreds = append(workerCreds, m)
}
resp := &pbs.LookupSessionResponse{
Authorization: &targets.SessionAuthorizationData{
SessionId: sessionInfo.GetPublicId(),
@ -293,6 +310,7 @@ func (ws *workerServiceServer) LookupSession(ctx context.Context, req *pbs.Looku
HostSetId: sessionInfo.HostSetId,
TargetId: sessionInfo.TargetId,
UserId: sessionInfo.UserId,
Credentials: workerCreds,
}
if resp.ConnectionsLeft != -1 {
resp.ConnectionsLeft -= int32(authzSummary.CurrentConnectionCount)

@ -0,0 +1,173 @@
package workers_test
import (
"context"
"sync"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/db"
pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers"
"github.com/hashicorp/boundary/internal/servers/controller/handlers/workers"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
func TestLookupSession(t *testing.T) {
ctx := context.Background()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
serversRepoFn := func() (*servers.Repository, error) {
return servers.NewRepository(rw, rw, kms)
}
sessionRepoFn := func() (*session.Repository, error) {
return session.NewRepository(rw, rw, kms)
}
at := authtoken.TestAuthToken(t, conn, kms, org.GetPublicId())
uId := at.GetIamUserId()
hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0]
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
sess := session.TestSession(t, conn, wrapper, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: prj.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
})
egressSess := session.TestSession(t, conn, wrapper, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: prj.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
})
repo, err := sessionRepoFn()
require.NoError(t, err)
creds := []*pbs.Credential{
{
Credential: &pbs.Credential_UserPassword{
UserPassword: &pbs.UserPassword{
Username: "username",
Password: "password",
},
},
},
{
Credential: &pbs.Credential_UserPassword{
UserPassword: &pbs.UserPassword{
Username: "another-username",
Password: "a different password",
},
},
},
}
workerCreds := make([]session.Credential, 0, len(creds))
for _, c := range creds {
data, err := proto.Marshal(c)
require.NoError(t, err)
workerCreds = append(workerCreds, data)
}
err = repo.AddSessionCredentials(ctx, egressSess.ScopeId, egressSess.GetPublicId(), workerCreds)
require.NoError(t, err)
s := workers.NewWorkerServiceServer(serversRepoFn, sessionRepoFn, new(sync.Map), kms)
require.NotNil(t, s)
cases := []struct {
name string
wantErr bool
wantErrMsg string
want *pbs.LookupSessionResponse
sessionId string
}{
{
name: "Invalid session id",
sessionId: "s_fakesession",
wantErr: true,
wantErrMsg: "rpc error: code = PermissionDenied desc = Unknown session ID.",
},
{
name: "Valid",
sessionId: sess.PublicId,
want: &pbs.LookupSessionResponse{
ConnectionLimit: 1,
ConnectionsLeft: 1,
Version: 1,
Endpoint: sess.Endpoint,
HostId: sess.HostId,
HostSetId: sess.HostSetId,
TargetId: sess.TargetId,
UserId: sess.UserId,
Status: pbs.SESSIONSTATUS_SESSIONSTATUS_PENDING,
},
},
{
name: "Valid-with-egress-creds",
sessionId: egressSess.PublicId,
want: &pbs.LookupSessionResponse{
ConnectionLimit: 1,
ConnectionsLeft: 1,
Version: 1,
Endpoint: egressSess.Endpoint,
HostId: egressSess.HostId,
HostSetId: egressSess.HostSetId,
TargetId: egressSess.TargetId,
UserId: egressSess.UserId,
Status: pbs.SESSIONSTATUS_SESSIONSTATUS_PENDING,
Credentials: creds,
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
req := &pbs.LookupSessionRequest{
SessionId: tc.sessionId,
}
got, err := s.LookupSession(ctx, req)
if tc.wantErr {
require.Error(err)
assert.Nil(got)
assert.Equal(tc.wantErrMsg, err.Error())
return
}
assert.Empty(
cmp.Diff(
tc.want,
got,
cmpopts.IgnoreUnexported(pbs.LookupSessionResponse{}, pbs.Credential{}, pbs.UserPassword{}),
cmpopts.IgnoreFields(pbs.LookupSessionResponse{}, "Expiration", "Authorization"),
),
)
})
}
}

@ -93,6 +93,7 @@ func (w *Worker) handleProxy(listenerCfg *listenerutil.ListenerConfig) (http.Han
tofuToken := si.LookupSessionResponse.GetTofuToken()
version := si.LookupSessionResponse.GetVersion()
endpoint := si.LookupSessionResponse.GetEndpoint()
credentials := si.LookupSessionResponse.GetCredentials()
sessStatus := si.Status
si.RUnlock()
@ -249,7 +250,12 @@ func (w *Worker) handleProxy(listenerCfg *listenerutil.ListenerConfig) (http.Han
return
}
if err = handleProxyFn(connCtx, conf); err != nil {
var proxyOpts []proxyHandlers.Option
if len(credentials) > 0 {
proxyOpts = append(proxyOpts, proxyHandlers.WithEgressCredentials(credentials))
}
if err = handleProxyFn(connCtx, conf, proxyOpts...); err != nil {
event.WriteError(ctx, op, err, event.WithInfoMsg("error handling proxy", "session_id", sessionId, "endpoint", endpoint))
if err = conn.Close(websocket.StatusInternalError, "unable to establish proxy"); err != nil {
event.WriteError(ctx, op, err, event.WithInfoMsg("error closing client connection"))

@ -1,7 +1,7 @@
package proxy
import (
"github.com/hashicorp/boundary/internal/credential"
serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
)
// Option - how Options are passed as arguments.
@ -18,7 +18,7 @@ func GetOpts(opt ...Option) Options {
// Options = how options are represented
type Options struct {
WithEgressCredentials []credential.Credential
WithEgressCredentials []*serverpb.Credential
}
func getDefaultOptions() Options {
@ -28,7 +28,7 @@ func getDefaultOptions() Options {
}
// WithEgressCredentials provides an optional egress credentials to use when establishing a proxy
func WithEgressCredentials(creds []credential.Credential) Option {
func WithEgressCredentials(creds []*serverpb.Credential) Option {
return func(o *Options) {
o.WithEgressCredentials = creds
}

@ -3,28 +3,27 @@ package proxy
import (
"testing"
"github.com/hashicorp/boundary/internal/credential"
serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
"github.com/stretchr/testify/assert"
)
type cred struct {
id string
secret string
}
func (c cred) GetPublicId() string { return c.id }
func (c cred) Secret() credential.SecretData { return c.secret }
func Test_GetOpts(t *testing.T) {
t.Parallel()
t.Run("WithEgressCredentials", func(t *testing.T) {
assert := assert.New(t)
c := cred{id: "test", secret: "hello"}
opts := GetOpts(WithEgressCredentials([]credential.Credential{c}))
c := &serverpb.Credential{
Credential: &serverpb.Credential_UserPassword{
UserPassword: &serverpb.UserPassword{
Username: "user",
Password: "pass",
},
},
}
opts := GetOpts(WithEgressCredentials([]*serverpb.Credential{c}))
testOpts := getDefaultOptions()
assert.NotEqual(opts, testOpts)
testOpts.WithEgressCredentials = []credential.Credential{c}
testOpts.WithEgressCredentials = []*serverpb.Credential{c}
assert.Equal(opts, testOpts)
})
}

Loading…
Cancel
Save