Merge branch 'main' into plugin-hostcatalogs

This commit is contained in:
Jeff Mitchell committed 2021-11-04 09:02:39 -04:00
commit 80d41b9044
79 files changed
+3965 -927

No files matched your search

+3
View File
@@ -22,6 +22,9 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.
a missing mandated cipher suite of the HTTP/2 (`h2`) specification that could
result in no shared cipher suites between the Boundary API listener and those
clients. ([PR](https://github.com/hashicorp/boundary/pull/1637))
* vault: Fix credential store support when using Vault namespaces
([Issue](https://github.com/hashicorp/boundary/issues/1597),
[PR](https://github.com/hashicorp/boundary/pull/1660))
## 0.6.2 (2021/09/27)
+9
View File
@@ -144,6 +144,15 @@ $ make test-database-up
$ make test
```
By default the container name is `boundary-sql-tests`.
This can be changed in the same way as the port:
```
$ export TEST_CONTAINER_NAME="custom-name"
$ make test-database-up
$ docker logs custom-name
```
The default docker image is built using the `postgres:11` base image.
The image can be changed using a make option to test against other versions:
+1
View File
@@ -127,6 +127,7 @@ protobuild:
@protoc-go-inject-tag -input=./internal/kms/store/session_key.pb.go
@protoc-go-inject-tag -input=./internal/kms/store/oidc_key.pb.go
@protoc-go-inject-tag -input=./internal/target/store/target.pb.go
@protoc-go-inject-tag -input=./internal/target/targettest/store/target.pb.go
@protoc-go-inject-tag -input=./internal/target/tcp/store/target.pb.go
@protoc-go-inject-tag -input=./internal/auth/oidc/store/oidc.pb.go
@protoc-go-inject-tag -input=./internal/scheduler/job/store/job.pb.go
+1
View File
@@ -88,6 +88,7 @@ for permanent installations, are detailed in our [Installation Guide](https://ww
If you have the following requirements met locally:
- Golang v1.16 or greater
- Docker
- [Boundary UI Dependencies](https://github.com/hashicorp/boundary-ui#prerequisites)
You can get up and running with Boundary quickly. Simply run:
+12
View File
@@ -159,6 +159,18 @@ func DefaultDescription() Option {
}
}
func WithEgressCredentialSourceIds(inEgressCredentialSourceIds []string) Option {
return func(o *options) {
o.postMap["egress_credential_source_ids"] = inEgressCredentialSourceIds
}
}
func DefaultEgressCredentialSourceIds() Option {
return func(o *options) {
o.postMap["egress_credential_source_ids"] = nil
}
}
func WithHostId(inHostId string) Option {
return func(o *options) {
o.postMap["host_id"] = inHostId
+2
View File
@@ -33,6 +33,8 @@ type Target struct {
ApplicationCredentialLibraries []*CredentialLibrary `json:"application_credential_libraries,omitempty"`
ApplicationCredentialSourceIds []string `json:"application_credential_source_ids,omitempty"`
ApplicationCredentialSources []*CredentialSource `json:"application_credential_sources,omitempty"`
EgressCredentialSourceIds []string `json:"egress_credential_source_ids,omitempty"`
EgressCredentialSources []*CredentialSource `json:"egress_credential_sources,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"`
AuthorizedActions []string `json:"authorized_actions,omitempty"`
+2
View File
@@ -64,4 +64,6 @@ const (
PluginNameField = "plugin_name"
IpAddressesField = "ip_addresses"
DnsNamesField = "dns_names"
EgressCredentialSourceIdsField = "egress_credential_source_ids"
EgressCredentialSourcesField = "egress_credential_sources"
)
+1 -1
View File
@@ -25,7 +25,7 @@ require (
github.com/hashicorp/dawdle v0.4.0
github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8
github.com/hashicorp/eventlogger v0.1.0
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239
github.com/hashicorp/go-bexpr v0.1.10
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-hclog v0.16.2
+2 -2
View File
@@ -478,8 +478,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/eventlogger v0.1.0 h1:S6xc4gZVzewuDUP4R4Ngko419h/CGDuV/b4ADL3XLik=
github.com/hashicorp/eventlogger v0.1.0/go.mod h1:a3IXf1aEJfpCPzseTOrwKj4fVW/Qn3oEmpQeaIznzH0=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5 h1:kNkH4G6zzWlZSoI1I+B/ud4chVKTPL516C6jB7dRdlE=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5/go.mod h1:8rcez7Kw1zanB0/074qnOuGu7zxmNh9Xr2ZI+K4xVIA=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239 h1:Yh9tY0lige+y0trmjQeT9NRDo6+YvtNAzbmUNOsIUzI=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239/go.mod h1:8rcez7Kw1zanB0/074qnOuGu7zxmNh9Xr2ZI+K4xVIA=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+5
View File
@@ -670,6 +670,11 @@ var inputStructs = []*structInfo{
ProtoName: "application_credential_source_ids",
FieldType: "[]string",
},
{
Name: "EgressCredentialSourceIds",
ProtoName: "egress_credential_source_ids",
FieldType: "[]string",
},
},
versionEnabled: true,
typeOnCreate: true,
+7 -14
View File
@@ -2,10 +2,6 @@ package oidc
import (
"context"
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/url"
"sort"
@@ -13,7 +9,7 @@ import (
"github.com/hashicorp/boundary/internal/auth/oidc/store"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/libs/crypto"
"github.com/hashicorp/boundary/internal/oplog"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/structwrapping"
@@ -236,17 +232,14 @@ func (a *AuthMethod) hmacClientSecret(ctx context.Context, cipher wrapping.Wrapp
if cipher == nil {
return errors.New(ctx, errors.InvalidParameter, op, "missing cipher")
}
reader, err := kms.NewDerivedReader(cipher, 32, []byte(a.PublicId), nil)
// this operation currently uses the legacy WithEd25519 option for hmac'ing.
// we should likely deprecate this and introduce a new "crypto version" of
// this attribute.
hm, err := crypto.HmacSha256(ctx, []byte(a.ClientSecret), cipher, []byte(a.PublicId), nil, crypto.WithBase64Encoding(), crypto.WithEd25519())
if err != nil {
return errors.Wrap(ctx, err, op)
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Code(errors.Encryption)))
}
key, _, err := ed25519.GenerateKey(reader)
if err != nil {
return errors.New(ctx, errors.Encrypt, op, "unable to generate derived key")
}
mac := hmac.New(sha256.New, key)
_, _ = mac.Write([]byte(a.ClientSecret))
a.ClientSecretHmac = base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
a.ClientSecretHmac = hm
return nil
}
+2 -1
View File
@@ -11,6 +11,7 @@ import (
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/libs/crypto"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
@@ -189,7 +190,7 @@ func requestWrappingWrapper(ctx context.Context, k *kms.Kms, scopeId, authMethod
}
// okay, I guess we need to derive a new key for this combo of oidcWrapper and authMethod
reader, err := kms.NewDerivedReader(oidcWrapper, 32, []byte(authMethodId), []byte(scopeId))
reader, err := crypto.NewDerivedReader(oidcWrapper, 32, []byte(authMethodId), []byte(scopeId))
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
+37 -10
View File
@@ -33,6 +33,7 @@ type extraCmdVars struct {
flagHostSources []string
flagApplicationCredentialLibraries []string
flagApplicationCredentialSources []string
flagEgressCredentialSources []string
flagHostId string
sar *targets.SessionAuthorizationResult
}
@@ -49,9 +50,9 @@ func extraActionsFlagsMapFuncImpl() map[string][]string {
"add-credential-libraries": {"id", "application-credential-library", "version"},
"remove-credential-libraries": {"id", "application-credential-library", "version"},
"set-credential-libraries": {"id", "application-credential-library", "version"},
"add-credential-sources": {"id", "application-credential-source", "version"},
"remove-credential-sources": {"id", "application-credential-source", "version"},
"set-credential-sources": {"id", "application-credential-source", "version"},
"add-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
"remove-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
"set-credential-sources": {"id", "application-credential-source", "egress-credential-source", "version"},
}
}
@@ -361,6 +362,12 @@ func extraFlagsFuncImpl(c *Command, _ *base.FlagSets, f *base.FlagSet) {
Target: &c.flagApplicationCredentialSources,
Usage: "The credential source for application purpose to add, set, or remove. May be specified multiple times.",
})
case "egress-credential-source":
f.StringSliceVar(&base.StringSliceVar{
Name: "egress-credential-source",
Target: &c.flagEgressCredentialSources,
Usage: "The credential source for egress purpose to add, set, or remove. May be specified multiple times.",
})
}
}
@@ -460,7 +467,6 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
}
case "add-credential-libraries", "remove-credential-libraries":
// TODO: As we add other purposes, add them to this check
if len(c.flagApplicationCredentialLibraries) == 0 {
c.UI.Error("No credential-libraries supplied via -application-credential-library")
return false
@@ -469,14 +475,19 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
case "add-credential-sources", "remove-credential-sources":
// TODO: As we add other purposes, add them to this check
if len(c.flagApplicationCredentialSources) == 0 {
c.UI.Error("No credential sources supplied via -application-credential-source")
if len(c.flagApplicationCredentialSources)+len(c.flagEgressCredentialSources) == 0 {
c.UI.Error("No credential sources supplied via -application-credential-source or -egress-credential-source")
return false
}
*opts = append(*opts, targets.WithApplicationCredentialSourceIds(c.flagApplicationCredentialSources))
if len(c.flagApplicationCredentialSources) > 0 {
*opts = append(*opts, targets.WithApplicationCredentialSourceIds(c.flagApplicationCredentialSources))
}
if len(c.flagEgressCredentialSources) > 0 {
*opts = append(*opts, targets.WithEgressCredentialSourceIds(c.flagEgressCredentialSources))
}
case "set-credential-libraries":
// TODO: As we add other purposes, add them to this check
switch len(c.flagApplicationCredentialLibraries) {
case 0:
c.UI.Error("No credential-libraries supplied via -application-credential-library")
@@ -493,10 +504,14 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
case "set-credential-sources":
// TODO: As we add other purposes, add them to this check
if len(c.flagApplicationCredentialSources)+len(c.flagEgressCredentialSources) == 0 {
c.UI.Error("No credential sources supplied via -application-credential-source or -egress-credential-source")
return false
}
switch len(c.flagApplicationCredentialSources) {
case 0:
c.UI.Error("No credential sources supplied via -application-credential-source")
return false
// do nothing
case 1:
if c.flagApplicationCredentialSources[0] == "null" {
*opts = append(*opts, targets.DefaultApplicationCredentialSourceIds())
@@ -506,6 +521,18 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
default:
*opts = append(*opts, targets.WithApplicationCredentialSourceIds(c.flagApplicationCredentialSources))
}
switch len(c.flagEgressCredentialSources) {
case 0:
// do nothing
case 1:
if c.flagEgressCredentialSources[0] == "null" {
*opts = append(*opts, targets.DefaultEgressCredentialSourceIds())
break
}
fallthrough
default:
*opts = append(*opts, targets.WithEgressCredentialSourceIds(c.flagEgressCredentialSources))
}
case "authorize-session":
if len(c.flagHostId) != 0 {
+11
View File
@@ -28,6 +28,10 @@ type Library interface {
// Purpose is the purpose of the credential.
type Purpose string
func (p Purpose) String() string {
return string(p)
}
// Credential purpose values.
const (
// ApplicationPurpose is a credential used for application specific
@@ -45,6 +49,13 @@ const (
EgressPurpose Purpose = "egress"
)
// ValidPurposes are the set of all credential Purposes.
var ValidPurposes = []Purpose{
ApplicationPurpose,
IngressPurpose,
EgressPurpose,
}
// SecretData represents secret data.
type SecretData interface{}
@@ -2,15 +2,12 @@ package vault
import (
"context"
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"database/sql"
"github.com/hashicorp/boundary/internal/credential/vault/store"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/libs/crypto"
"github.com/hashicorp/boundary/internal/oplog"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/structwrapping"
@@ -103,17 +100,14 @@ func (c *ClientCertificate) hmacCertificateKey(ctx context.Context, cipher wrapp
if cipher == nil {
return errors.New(ctx, errors.InvalidParameter, op, "missing cipher")
}
reader, err := kms.NewDerivedReader(cipher, 32, []byte(c.StoreId), nil)
// this operation currently uses the legacy WithEd25519 option for hmac'ing.
// we should likely deprecate this and introduce a new "crypto version" of
// this attribute.
hm, err := crypto.HmacSha256(ctx, c.CertificateKey, cipher, []byte(c.StoreId), nil, crypto.WithEd25519())
if err != nil {
return errors.Wrap(ctx, err, op)
}
key, _, err := ed25519.GenerateKey(reader)
if err != nil {
return errors.New(ctx, errors.Encrypt, op, "unable to generate derived key")
}
mac := hmac.New(sha256.New, key)
_, _ = mac.Write(c.CertificateKey)
c.CertificateKeyHmac = mac.Sum(nil)
c.CertificateKeyHmac = []byte(hm)
return nil
}
+4
View File
@@ -79,6 +79,10 @@ func newClient(c *clientConfig) (*client, error) {
}
vClient.SetToken(string(c.Token))
if c.Namespace != "" {
vClient.SetNamespace(c.Namespace)
}
return &client{
cl: vClient,
token: c.Token,
+6 -9
View File
@@ -2,18 +2,16 @@ package vault
import (
"context"
"crypto/hmac"
"crypto/sha256"
"database/sql"
"time"
"github.com/hashicorp/boundary/internal/credential/vault/store"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/libs/crypto"
"github.com/hashicorp/boundary/internal/oplog"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/structwrapping"
"golang.org/x/crypto/blake2b"
"google.golang.org/protobuf/proto"
)
@@ -74,16 +72,15 @@ func newToken(storeId string, token TokenSecret, accessor []byte, expiration tim
accessorCopy := make([]byte, len(accessor))
copy(accessorCopy, accessor)
key := blake2b.Sum256(accessorCopy)
mac := hmac.New(sha256.New, key[:])
_, _ = mac.Write(tokenCopy)
hmac := mac.Sum(nil)
hmac, err := crypto.HmacSha256WithPrk(context.Background(), tokenCopy, accessorCopy)
if err != nil {
return nil, errors.WrapDeprecated(err, op, errors.WithCode(errors.Encrypt))
}
t := &Token{
expiration: expiration.Round(time.Second),
Token: &store.Token{
StoreId: storeId,
TokenHmac: hmac,
TokenHmac: []byte(hmac),
Token: tokenCopy,
Status: string(CurrentToken),
},
+10 -8
View File
@@ -46,6 +46,16 @@ func UpdateFields(i interface{}, fieldMaskPaths []string, setToNullPaths []strin
val := reflect.Indirect(reflect.ValueOf(i))
structTyp := val.Type()
for i := 0; i < structTyp.NumField(); i++ {
if f, ok := maskPaths[strings.ToUpper(structTyp.Field(i).Name)]; ok {
updateFields[f] = val.Field(i).Interface()
found[strings.ToUpper(f)] = struct{}{}
continue
}
if f, ok := nullPaths[strings.ToUpper(structTyp.Field(i).Name)]; ok {
updateFields[f] = gorm.Expr("NULL")
found[strings.ToUpper(f)] = struct{}{}
continue
}
kind := structTyp.Field(i).Type.Kind()
if kind == reflect.Struct || kind == reflect.Ptr {
embType := structTyp.Field(i).Type
@@ -76,14 +86,6 @@ func UpdateFields(i interface{}, fieldMaskPaths []string, setToNullPaths []strin
continue
}
}
if f, ok := maskPaths[strings.ToUpper(structTyp.Field(i).Name)]; ok {
updateFields[f] = val.Field(i).Interface()
found[strings.ToUpper(f)] = struct{}{}
}
if f, ok := nullPaths[strings.ToUpper(structTyp.Field(i).Name)]; ok {
updateFields[f] = gorm.Expr("NULL")
found[strings.ToUpper(f)] = struct{}{}
}
}
if missing := findMissingPaths(setToNullPaths, found); len(missing) != 0 {
+18
View File
@@ -4,9 +4,13 @@ import (
"testing"
"github.com/hashicorp/boundary/internal/db/db_test"
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/go-secure-stdlib/base62"
"github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/gorm"
)
@@ -398,6 +402,20 @@ func TestUpdateFields(t *testing.T) {
assert.Equal(tt.want, got)
})
}
t.Run("valid-embedded-timestamp", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
wantTs := &timestamp.Timestamp{
Timestamp: &timestamppb.Timestamp{
Seconds: 1,
Nanos: 1,
},
}
u := testUser(t, "", "")
u.UpdateTime = wantTs
got, err := UpdateFields(u, []string{"UpdateTime"}, nil)
require.NoError(err)
assert.True(proto.Equal(wantTs, got["UpdateTime"].(*timestamp.Timestamp)))
})
}
func testUser(t *testing.T, name, email string) *db_test.TestUser {
+73 -4
View File
@@ -2,15 +2,19 @@
package db_test
import (
"errors"
"github.com/hashicorp/go-secure-stdlib/base62"
"google.golang.org/protobuf/proto"
)
const (
defaultUserTablename = "db_test_user"
defaultCarTableName = "db_test_car"
defaultRentalTableName = "db_test_rental"
defaultScooterTableName = "db_test_scooter"
defaultUserTablename = "db_test_user"
defaultCarTableName = "db_test_car"
defaultRentalTableName = "db_test_rental"
defaultScooterTableName = "db_test_scooter"
defaultAccessoryTableName = "db_test_accessory"
defaultScooterAccessoryTableName = "db_test_scooter_accessory"
)
type TestUser struct {
@@ -153,6 +157,71 @@ func (t *TestScooter) SetTableName(name string) {
t.table = name
}
type TestAccessory struct {
*StoreTestAccessory
table string `gorm:"-"`
}
func NewTestAccessory(description string) (*TestAccessory, error) {
if description == "" {
return nil, errors.New("missing description")
}
return &TestAccessory{StoreTestAccessory: &StoreTestAccessory{Description: description}}, nil
}
func (t *TestAccessory) Clone() interface{} {
s := proto.Clone(t.StoreTestAccessory)
return &TestAccessory{
StoreTestAccessory: s.(*StoreTestAccessory),
}
}
func (t *TestAccessory) TableName() string {
if t.table != "" {
return t.table
}
return defaultAccessoryTableName
}
func (t *TestAccessory) SetTableName(name string) {
t.table = name
}
type TestScooterAccessory struct {
*StoreTestScooterAccessory
table string `gorm:"-"`
}
func NewTestScooterAccessory(scooterId, accessoryId uint32) (*TestScooterAccessory, error) {
if accessoryId == 0 {
return nil, errors.New("mssing accessory id")
}
return &TestScooterAccessory{
StoreTestScooterAccessory: &StoreTestScooterAccessory{
ScooterId: scooterId,
AccessoryId: accessoryId,
},
}, nil
}
func (t *TestScooterAccessory) Clone() interface{} {
s := proto.Clone(t.StoreTestScooterAccessory)
return &TestScooterAccessory{
StoreTestScooterAccessory: s.(*StoreTestScooterAccessory),
}
}
func (t *TestScooterAccessory) TableName() string {
if t.table != "" {
return t.table
}
return defaultScooterAccessoryTableName
}
func (t *TestScooterAccessory) SetTableName(name string) {
t.table = name
}
type Cloner interface {
Clone() interface{}
}
+187 -21
View File
@@ -453,6 +453,133 @@ func (x *StoreTestScooter) GetMpg() int32 {
return 0
}
// StoreTestAccessory used in the db tests only and provides a gorm resource with
// an id that's not a private or public id
type StoreTestAccessory struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// @inject_tag: gorm:"primary_key"
AccessoryId uint32 `protobuf:"varint,1,opt,name=accessory_id,json=accessoryId,proto3" json:"accessory_id,omitempty" gorm:"primary_key"`
// @inject_tag: `gorm:"default:not_null"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" gorm:"default:not_null"`
}
func (x *StoreTestAccessory) Reset() {
*x = StoreTestAccessory{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StoreTestAccessory) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StoreTestAccessory) ProtoMessage() {}
func (x *StoreTestAccessory) ProtoReflect() protoreflect.Message {
mi := &file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[4]
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 StoreTestAccessory.ProtoReflect.Descriptor instead.
func (*StoreTestAccessory) Descriptor() ([]byte, []int) {
return file_controller_storage_db_db_test_v1_db_test_proto_rawDescGZIP(), []int{4}
}
func (x *StoreTestAccessory) GetAccessoryId() uint32 {
if x != nil {
return x.AccessoryId
}
return 0
}
func (x *StoreTestAccessory) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
// StoreTestScooterAccessory used in the db tests only and provides a gorm
// resource with multiple pks
type StoreTestScooterAccessory struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// @inject_tag: gorm:"primary_key"
AccessoryId uint32 `protobuf:"varint,1,opt,name=accessory_id,json=accessoryId,proto3" json:"accessory_id,omitempty" gorm:"primary_key"`
// @inject_tag: gorm:"primary_key"
ScooterId uint32 `protobuf:"varint,2,opt,name=scooter_id,json=scooterId,proto3" json:"scooter_id,omitempty" gorm:"primary_key"`
// @inject_tag: `gorm:"default:null"`
Review string `protobuf:"bytes,3,opt,name=review,proto3" json:"review,omitempty" gorm:"default:null"`
}
func (x *StoreTestScooterAccessory) Reset() {
*x = StoreTestScooterAccessory{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StoreTestScooterAccessory) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StoreTestScooterAccessory) ProtoMessage() {}
func (x *StoreTestScooterAccessory) ProtoReflect() protoreflect.Message {
mi := &file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[5]
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 StoreTestScooterAccessory.ProtoReflect.Descriptor instead.
func (*StoreTestScooterAccessory) Descriptor() ([]byte, []int) {
return file_controller_storage_db_db_test_v1_db_test_proto_rawDescGZIP(), []int{5}
}
func (x *StoreTestScooterAccessory) GetAccessoryId() uint32 {
if x != nil {
return x.AccessoryId
}
return 0
}
func (x *StoreTestScooterAccessory) GetScooterId() uint32 {
if x != nil {
return x.ScooterId
}
return 0
}
func (x *StoreTestScooterAccessory) GetReview() string {
if x != nil {
return x.Review
}
return ""
}
var File_controller_storage_db_db_test_v1_db_test_proto protoreflect.FileDescriptor
var file_controller_storage_db_db_test_v1_db_test_proto_rawDesc = []byte{
@@ -535,12 +662,25 @@ var file_controller_storage_db_db_test_v1_db_test_proto_rawDesc = []byte{
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x76, 0x61,
0x74, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x06, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x70,
0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, 0x70, 0x67, 0x42, 0x3b, 0x5a, 0x39,
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, 0x64, 0x62, 0x2f, 0x64, 0x62, 0x5f, 0x74, 0x65, 0x73,
0x74, 0x3b, 0x64, 0x62, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, 0x70, 0x67, 0x22, 0x59, 0x0a, 0x12,
0x53, 0x74, 0x6f, 0x72, 0x65, 0x54, 0x65, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f,
0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x75, 0x0a, 0x19, 0x53, 0x74, 0x6f, 0x72, 0x65,
0x54, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73,
0x73, 0x6f, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65,
0x73, 0x73, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x6f, 0x74,
0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x63, 0x6f,
0x6f, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x42, 0x3b,
0x5a, 0x39, 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, 0x64, 0x62, 0x2f, 0x64, 0x62, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x3b, 0x64, 0x62, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
@@ -555,23 +695,25 @@ func file_controller_storage_db_db_test_v1_db_test_proto_rawDescGZIP() []byte {
return file_controller_storage_db_db_test_v1_db_test_proto_rawDescData
}
var file_controller_storage_db_db_test_v1_db_test_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_controller_storage_db_db_test_v1_db_test_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_controller_storage_db_db_test_v1_db_test_proto_goTypes = []interface{}{
(*StoreTestUser)(nil), // 0: controller.storage.db.db_test.v1.StoreTestUser
(*StoreTestCar)(nil), // 1: controller.storage.db.db_test.v1.StoreTestCar
(*StoreTestRental)(nil), // 2: controller.storage.db.db_test.v1.StoreTestRental
(*StoreTestScooter)(nil), // 3: controller.storage.db.db_test.v1.StoreTestScooter
(*timestamp.Timestamp)(nil), // 4: controller.storage.timestamp.v1.Timestamp
(*StoreTestUser)(nil), // 0: controller.storage.db.db_test.v1.StoreTestUser
(*StoreTestCar)(nil), // 1: controller.storage.db.db_test.v1.StoreTestCar
(*StoreTestRental)(nil), // 2: controller.storage.db.db_test.v1.StoreTestRental
(*StoreTestScooter)(nil), // 3: controller.storage.db.db_test.v1.StoreTestScooter
(*StoreTestAccessory)(nil), // 4: controller.storage.db.db_test.v1.StoreTestAccessory
(*StoreTestScooterAccessory)(nil), // 5: controller.storage.db.db_test.v1.StoreTestScooterAccessory
(*timestamp.Timestamp)(nil), // 6: controller.storage.timestamp.v1.Timestamp
}
var file_controller_storage_db_db_test_v1_db_test_proto_depIdxs = []int32{
4, // 0: controller.storage.db.db_test.v1.StoreTestUser.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 1: controller.storage.db.db_test.v1.StoreTestUser.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 2: controller.storage.db.db_test.v1.StoreTestCar.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 3: controller.storage.db.db_test.v1.StoreTestCar.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 4: controller.storage.db.db_test.v1.StoreTestRental.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 5: controller.storage.db.db_test.v1.StoreTestRental.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 6: controller.storage.db.db_test.v1.StoreTestScooter.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
4, // 7: controller.storage.db.db_test.v1.StoreTestScooter.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 0: controller.storage.db.db_test.v1.StoreTestUser.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 1: controller.storage.db.db_test.v1.StoreTestUser.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 2: controller.storage.db.db_test.v1.StoreTestCar.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 3: controller.storage.db.db_test.v1.StoreTestCar.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 4: controller.storage.db.db_test.v1.StoreTestRental.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 5: controller.storage.db.db_test.v1.StoreTestRental.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 6: controller.storage.db.db_test.v1.StoreTestScooter.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
6, // 7: controller.storage.db.db_test.v1.StoreTestScooter.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
@@ -633,6 +775,30 @@ func file_controller_storage_db_db_test_v1_db_test_proto_init() {
return nil
}
}
file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StoreTestAccessory); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_controller_storage_db_db_test_v1_db_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StoreTestScooterAccessory); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -640,7 +806,7 @@ func file_controller_storage_db_db_test_v1_db_test_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_storage_db_db_test_v1_db_test_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
+44 -17
View File
@@ -43,9 +43,11 @@ const (
// Reader interface defines lookups/searching for resources
type Reader interface {
// LookupById will lookup a resource by its primary key id, which must be
// unique. The resourceWithIder must implement either ResourcePublicIder or
// ResourcePrivateIder interface.
LookupById(ctx context.Context, resourceWithIder interface{}, opt ...Option) error
// unique. If the resource implements either ResourcePublicIder or
// ResourcePrivateIder interface, then they are used as the resource's
// primary key for lookup. Otherwise, the resource tags are used to
// determine it's primary key(s) for lookup.
LookupById(ctx context.Context, resource interface{}, opt ...Option) error
// LookupByPublicId will lookup resource by its public_id which must be unique.
LookupByPublicId(ctx context.Context, resource ResourcePublicIder, opt ...Option) error
@@ -1048,11 +1050,11 @@ func (rw *Db) LookupById(ctx context.Context, resourceWithIder interface{}, _ ..
if reflect.ValueOf(resourceWithIder).Kind() != reflect.Ptr {
return errors.New(ctx, errors.InvalidParameter, op, "interface parameter must to be a pointer")
}
primaryKey, where, err := primaryKeyWhere(ctx, resourceWithIder)
where, keys, err := rw.primaryKeysWhere(ctx, resourceWithIder)
if err != nil {
return errors.Wrap(ctx, err, op)
}
if err := rw.underlying.Where(where, primaryKey).First(resourceWithIder).Error; err != nil {
if err := rw.underlying.Where(where, keys...).First(resourceWithIder).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op), errors.WithoutEvent())
}
@@ -1061,23 +1063,48 @@ func (rw *Db) LookupById(ctx context.Context, resourceWithIder interface{}, _ ..
return nil
}
func primaryKeyWhere(ctx context.Context, resourceWithIder interface{}) (pkey string, w string, e error) {
const op = "db.primaryKeyWhere"
var primaryKey, where string
switch resourceType := resourceWithIder.(type) {
func (rw *Db) primaryKeysWhere(ctx context.Context, i interface{}) (string, []interface{}, error) {
const op = "db.primaryKeysWhere"
var fieldNames []string
var fieldValues []interface{}
tx := rw.underlying.Model(i)
if err := tx.Statement.Parse(i); err != nil {
return "", nil, errors.Wrap(ctx, err, op, errors.WithoutEvent())
}
switch resourceType := i.(type) {
case ResourcePublicIder:
primaryKey = resourceType.GetPublicId()
where = "public_id = ?"
if resourceType.GetPublicId() == "" {
return "", nil, errors.New(ctx, errors.InvalidParameter, op, "missing primary key", errors.WithoutEvent())
}
fieldValues = []interface{}{resourceType.GetPublicId()}
fieldNames = []string{"public_id"}
case ResourcePrivateIder:
primaryKey = resourceType.GetPrivateId()
where = "private_id = ?"
if resourceType.GetPrivateId() == "" {
return "", nil, errors.New(ctx, errors.InvalidParameter, op, "missing primary key", errors.WithoutEvent())
}
fieldValues = []interface{}{resourceType.GetPrivateId()}
fieldNames = []string{"private_id"}
default:
return "", "", errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported interface type %T", resourceWithIder), errors.WithoutEvent())
v := reflect.ValueOf(i)
for _, f := range tx.Statement.Schema.PrimaryFields {
if f.PrimaryKey {
val, isZero := f.ValueOf(v)
if isZero {
return "", nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("primary field %s is zero", f.Name))
}
fieldNames = append(fieldNames, f.DBName)
fieldValues = append(fieldValues, val)
}
}
}
if primaryKey == "" {
return "", "", errors.New(ctx, errors.InvalidParameter, op, "missing primary key", errors.WithoutEvent())
if len(fieldNames) == 0 {
return "", nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("no primary key(s) for %t", i))
}
return primaryKey, where, nil
clauses := make([]string, 0, len(fieldNames))
for _, col := range fieldNames {
clauses = append(clauses, fmt.Sprintf("%s = ?", col))
}
return strings.Join(clauses, " and "), fieldValues, nil
}
// LookupByPublicId will lookup resource by its public_id, which must be unique.
+90 -11
View File
@@ -571,6 +571,17 @@ func TestDb_Update(t *testing.T) {
assert.Equal(0, rowsUpdated)
assert.Contains(err.Error(), "db.Update: oplog validation failed: db.validateOplogArgs: missing metadata: parameter violation: error #100")
})
t.Run("multi-column", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
w := Db{underlying: db}
scooter := testScooter(t, db, "", 0)
accessory := testAccessory(t, db, "test accessory")
scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId)
scooterAccessory.Review = "this is great"
rowsUpdated, err := w.Update(context.Background(), scooterAccessory, []string{"Review"}, nil)
require.NoError(err)
assert.Equal(1, rowsUpdated)
})
}
// testUserWithVet gives us a model that implements VetForWrite() without any
@@ -826,7 +837,7 @@ func TestDb_LookupByPublicId(t *testing.T) {
require.NoError(err)
err = w.LookupByPublicId(context.Background(), foundUser)
require.Error(err)
assert.Contains(err.Error(), "db.LookupById: db.primaryKeyWhere: missing primary key: parameter violation: error #100")
assert.Contains(err.Error(), "db.LookupById: db.primaryKeysWhere: missing primary key: parameter violation: error #100")
})
t.Run("not-found", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
@@ -1448,6 +1459,16 @@ func TestDb_Delete(t *testing.T) {
err = TestVerifyOplog(t, &w, user.PublicId, WithOperation(oplog.OpType_OP_TYPE_UNSPECIFIED), WithCreateNotBefore(10*time.Second))
require.NoError(err)
})
t.Run("multi-column", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
w := Db{underlying: db}
scooter := testScooter(t, db, "", 0)
accessory := testAccessory(t, db, "test accessory")
scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId)
rowsDeleted, err := w.Delete(context.Background(), scooterAccessory)
require.NoError(err)
assert.Equal(1, rowsDeleted)
})
}
}
@@ -1983,14 +2004,41 @@ func testScooter(t *testing.T, conn *DB, model string, mpg int32) *db_test.TestS
return u
}
func testAccessory(t *testing.T, conn *DB, description string) *db_test.TestAccessory {
t.Helper()
require := require.New(t)
a, err := db_test.NewTestAccessory(description)
require.NoError(err)
if conn != nil {
err = conn.Create(a).Error
require.NoError(err)
}
return a
}
func testScooterAccessory(t *testing.T, conn *DB, scooterId, accessoryId uint32) *db_test.TestScooterAccessory {
t.Helper()
require := require.New(t)
a, err := db_test.NewTestScooterAccessory(scooterId, accessoryId)
require.NoError(err)
if conn != nil {
err = conn.Create(a).Error
require.NoError(err)
}
return a
}
func TestDb_LookupById(t *testing.T) {
t.Parallel()
db, _ := TestSetup(t, "postgres")
scooter := testScooter(t, db, "", 0)
user := testUser(t, db, "", "", "")
accessory := testAccessory(t, db, "test accessory")
scooterAccessory := testScooterAccessory(t, db, scooter.Id, accessory.AccessoryId)
type args struct {
resourceWithIder interface{}
opt []Option
resource interface{}
opt []Option
}
tests := []struct {
name string
@@ -2004,7 +2052,7 @@ func TestDb_LookupById(t *testing.T) {
name: "simple-private-id",
underlying: db,
args: args{
resourceWithIder: scooter,
resource: scooter,
},
wantErr: false,
want: scooter,
@@ -2013,16 +2061,47 @@ func TestDb_LookupById(t *testing.T) {
name: "simple-public-id",
underlying: db,
args: args{
resourceWithIder: user,
resource: user,
},
wantErr: false,
want: user,
},
{
name: "simple-non-public-non-private-id",
underlying: db,
args: args{
resource: accessory,
},
wantErr: false,
want: accessory,
},
{
name: "compond",
underlying: db,
args: args{
resource: scooterAccessory,
},
wantErr: false,
want: scooterAccessory,
},
{
name: "compond-with-zero-value-pk",
underlying: db,
args: args{
resource: func() interface{} {
cp := scooterAccessory.Clone()
cp.(*db_test.TestScooterAccessory).ScooterId = 0
return cp
}(),
},
wantErr: true,
wantIsErr: errors.InvalidParameter,
},
{
name: "missing-public-id",
underlying: db,
args: args{
resourceWithIder: &db_test.TestUser{
resource: &db_test.TestUser{
StoreTestUser: &db_test.StoreTestUser{},
},
},
@@ -2033,7 +2112,7 @@ func TestDb_LookupById(t *testing.T) {
name: "missing-private-id",
underlying: db,
args: args{
resourceWithIder: &db_test.TestScooter{
resource: &db_test.TestScooter{
StoreTestScooter: &db_test.StoreTestScooter{},
},
},
@@ -2044,7 +2123,7 @@ func TestDb_LookupById(t *testing.T) {
name: "not-an-ider",
underlying: db,
args: args{
resourceWithIder: &db_test.NotIder{},
resource: &db_test.NotIder{},
},
wantErr: true,
wantIsErr: errors.InvalidParameter,
@@ -2053,7 +2132,7 @@ func TestDb_LookupById(t *testing.T) {
name: "missing-underlying-db",
underlying: nil,
args: args{
resourceWithIder: user,
resource: user,
},
wantErr: true,
wantIsErr: errors.InvalidParameter,
@@ -2065,13 +2144,13 @@ func TestDb_LookupById(t *testing.T) {
rw := &Db{
underlying: tt.underlying,
}
cloner, ok := tt.args.resourceWithIder.(db_test.Cloner)
cloner, ok := tt.args.resource.(db_test.Cloner)
require.True(ok)
cp := cloner.Clone()
err := rw.LookupById(context.Background(), cp, tt.args.opt...)
if tt.wantErr {
require.Error(err)
require.True(errors.Match(errors.T(tt.wantIsErr), err))
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "want err code: %q got: %q", tt.wantIsErr, err)
return
}
require.NoError(err)
@@ -0,0 +1,56 @@
begin;
create table if not exists db_test_accessory (
accessory_id bigint generated always as identity primary key,
create_time wt_timestamp,
update_time wt_timestamp,
description text not null
);
create trigger
update_time_column
before
update on db_test_accessory
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on db_test_accessory
for each row execute procedure immutable_columns('create_time');
create trigger
default_create_time_column
before
insert on db_test_accessory
for each row execute procedure default_create_time();
create table if not exists db_test_scooter_accessory (
accessory_id bigint references db_test_accessory(accessory_id),
scooter_id bigint references db_test_scooter(id),
create_time wt_timestamp,
update_time wt_timestamp,
review text,
primary key(accessory_id, scooter_id)
);
create trigger
update_time_column
before
update on db_test_scooter_accessory
for each row execute procedure update_time_column();
create trigger
immutable_columns
before
update on db_test_scooter_accessory
for each row execute procedure immutable_columns('create_time');
create trigger
default_create_time_column
before
insert on db_test_scooter_accessory
for each row execute procedure default_create_time();
commit;
@@ -165,16 +165,19 @@ func testSessionCredentialParams(t *testing.T, conn *db.DB, kms *kms.Kms, wrappe
ctx := context.Background()
stores := vault.TestCredentialStores(t, conn, wrapper, tar.GetScopeId(), 1)
libs := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2)
libIds := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2)
libs := []*target.CredentialLibrary{
target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.ApplicationPurpose),
target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.ApplicationPurpose),
}
targetRepo, err := target.NewRepository(rw, rw, kms)
require.NoError(t, err)
_, _, _, err = targetRepo.AddTargetCredentialSources(ctx, tar.GetPublicId(), tar.GetVersion(), []string{libs[0].PublicId, libs[1].PublicId})
_, _, _, err = targetRepo.AddTargetCredentialSources(ctx, tar.GetPublicId(), tar.GetVersion(), libs)
require.NoError(t, err)
creds := []*session.DynamicCredential{
session.NewDynamicCredential(libs[0].GetPublicId(), credential.ApplicationPurpose),
session.NewDynamicCredential(libs[0].GetPublicId(), credential.IngressPurpose),
session.NewDynamicCredential(libs[1].GetPublicId(), credential.EgressPurpose),
session.NewDynamicCredential(libIds[0].GetPublicId(), credential.ApplicationPurpose),
session.NewDynamicCredential(libIds[1].GetPublicId(), credential.ApplicationPurpose),
}
return creds
}
+9 -7
View File
@@ -21,6 +21,8 @@ POSTGRES_DOCKER_IMAGE := $(POSTGRES_DOCKER_IMAGE_BASE):$(PG_DOCKER_TAG)
PG_TAP_DOCKER_IMAGE_BASE ?= subzerocloud/pgtap
PG_TAP_DOCKER_IMAGE := $(PG_TAP_DOCKER_IMAGE_BASE):$(PG_TAP_DOCKER_TAG)
SQL_TEST_CONTAINER_NAME ?= boundary-sql-tests
# re-write paths for docker
dockerized_tests = $(patsubst tests/%,/test/%,$(TESTS))
@@ -29,7 +31,7 @@ test:
@echo Using $(POSTGRES_DOCKER_IMAGE)
@echo Using $(PG_TAP_DOCKER_IMAGE)
@docker run -d \
--name boundary-sql-tests \
--name $(SQL_TEST_CONTAINER_NAME) \
-e POSTGRES_PASSWORD=boundary \
-e POSTGRES_USER=boundary \
-e POSTGRES_DB=boundary \
@@ -38,7 +40,7 @@ test:
$(POSTGRES_DOCKER_IMAGE)
@docker run -it --rm \
--name test \
--link boundary-sql-tests:db \
--link $(SQL_TEST_CONTAINER_NAME):db \
-e DATABASE=boundary \
-e HOST=db \
-e PORT=5432 \
@@ -47,12 +49,12 @@ test:
-e TESTS="$(PROVE_OPTS) $(dockerized_tests)" \
-v "$(CWD)/tests":/test \
$(PG_TAP_DOCKER_IMAGE); \
(ret=$$?; docker stop boundary-sql-tests &>/dev/null && docker rm -v boundary-sql-tests &>/dev/null && exit $$ret)
(ret=$$?; docker stop $(SQL_TEST_CONTAINER_NAME) &>/dev/null && docker rm -v $(SQL_TEST_CONTAINER_NAME) &>/dev/null && exit $$ret)
database-up:
@echo Using $(POSTGRES_DOCKER_IMAGE)
@docker run -d \
--name boundary-sql-tests \
--name $(SQL_TEST_CONTAINER_NAME) \
-e POSTGRES_PASSWORD=boundary \
-e POSTGRES_USER=boundary \
-e POSTGRES_DB=boundary \
@@ -64,7 +66,7 @@ run-tests:
@echo Using $(PG_TAP_DOCKER_IMAGE)
@docker run -it --rm \
--name test \
--link boundary-sql-tests:db \
--link $(SQL_TEST_CONTAINER_NAME):db \
-e DATABASE=boundary \
-e HOST=db \
-e PORT=5432 \
@@ -75,7 +77,7 @@ run-tests:
$(PG_TAP_DOCKER_IMAGE)
clean:
docker stop boundary-sql-tests || true
docker rm -v boundary-sql-tests || true
docker stop $(SQL_TEST_CONTAINER_NAME) || true
docker rm -v $(SQL_TEST_CONTAINER_NAME) || true
.PHONY: all clean test database-up run-tests
+35 -1
View File
@@ -2819,6 +2819,12 @@
"items": {
"type": "string"
}
},
"egress_credential_source_ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -3055,6 +3061,12 @@
"items": {
"type": "string"
}
},
"egress_credential_source_ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -3240,9 +3252,15 @@
"items": {
"type": "string"
}
},
"egress_credential_source_ids": {
"type": "array",
"items": {
"type": "string"
}
}
},
"description": "Sets the values for application_credential_source_ids. If any\ncredential_source_id field that is not set in the request will result in\nthose fields being cleared."
"description": "Sets the values for credential sources. Any credential_source_id field that\nis not set in the request will result in those fields being cleared."
}
}
],
@@ -5127,6 +5145,22 @@
"description": "Output only. The application credential sources associated with this Target.",
"readOnly": true
},
"egress_credential_source_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Output only. The IDs of the egress credential source ids associated with this Target.",
"readOnly": true
},
"egress_credential_sources": {
"type": "array",
"items": {
"$ref": "#/definitions/controller.api.resources.targets.v1.CredentialSource"
},
"description": "Output only. The egress credential sources associated with this Target.",
"readOnly": true
},
"attributes": {
"type": "object",
"description": "The attributes that are applicable for the specific Target."
@@ -10,6 +10,7 @@ import (
"github.com/hashicorp/boundary/sdk/pbs/controller/api"
"github.com/hashicorp/boundary/sdk/wrapper"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/eventlogger/filters/encrypt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
structpb "google.golang.org/protobuf/types/known/structpb"
@@ -81,7 +82,7 @@ func TestAuthenticate_Tags(t *testing.T) {
"auth_url": structpb.NewStringValue("public-auth_url"),
"token_id": structpb.NewStringValue("public-token_id"),
"final_redirect_url": structpb.NewStringValue("public-final_redirect_url"),
"token": structpb.NewStringValue("<REDACTED>"),
"token": structpb.NewStringValue(encrypt.RedactedData),
},
},
},
@@ -121,8 +122,8 @@ func TestAuthenticate_Tags(t *testing.T) {
"auth_url": structpb.NewStringValue("public-auth_url"),
"token_id": structpb.NewStringValue("public-token_id"),
"state": structpb.NewStringValue("public-state"),
"password": structpb.NewStringValue("<REDACTED>"),
"code": structpb.NewStringValue("<REDACTED>"),
"password": structpb.NewStringValue(encrypt.RedactedData),
"code": structpb.NewStringValue(encrypt.RedactedData),
},
},
},
@@ -1546,6 +1546,7 @@ type AddTargetCredentialSourcesRequest struct {
// The mutation will fail if the version does not match the latest known good version.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
ApplicationCredentialSourceIds []string `protobuf:"bytes,3,rep,name=application_credential_source_ids,proto3" json:"application_credential_source_ids,omitempty"`
EgressCredentialSourceIds []string `protobuf:"bytes,4,rep,name=egress_credential_source_ids,proto3" json:"egress_credential_source_ids,omitempty"`
}
func (x *AddTargetCredentialSourcesRequest) Reset() {
@@ -1601,6 +1602,13 @@ func (x *AddTargetCredentialSourcesRequest) GetApplicationCredentialSourceIds()
return nil
}
func (x *AddTargetCredentialSourcesRequest) GetEgressCredentialSourceIds() []string {
if x != nil {
return x.EgressCredentialSourceIds
}
return nil
}
type AddTargetCredentialSourcesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1648,9 +1656,8 @@ func (x *AddTargetCredentialSourcesResponse) GetItem() *targets.Target {
return nil
}
// Sets the values for application_credential_source_ids. If any
// credential_source_id field that is not set in the request will result in
// those fields being cleared.
// Sets the values for credential sources. Any credential_source_id field that
// is not set in the request will result in those fields being cleared.
type SetTargetCredentialSourcesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1661,6 +1668,7 @@ type SetTargetCredentialSourcesRequest struct {
// The mutation will fail if the version does not match the latest known good version.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
ApplicationCredentialSourceIds []string `protobuf:"bytes,3,rep,name=application_credential_source_ids,proto3" json:"application_credential_source_ids,omitempty"`
EgressCredentialSourceIds []string `protobuf:"bytes,4,rep,name=egress_credential_source_ids,proto3" json:"egress_credential_source_ids,omitempty"`
}
func (x *SetTargetCredentialSourcesRequest) Reset() {
@@ -1716,6 +1724,13 @@ func (x *SetTargetCredentialSourcesRequest) GetApplicationCredentialSourceIds()
return nil
}
func (x *SetTargetCredentialSourcesRequest) GetEgressCredentialSourceIds() []string {
if x != nil {
return x.EgressCredentialSourceIds
}
return nil
}
type SetTargetCredentialSourcesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1773,6 +1788,7 @@ type RemoveTargetCredentialSourcesRequest struct {
// The mutation will fail if the version does not match the latest known good version.
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
ApplicationCredentialSourceIds []string `protobuf:"bytes,3,rep,name=application_credential_source_ids,json=application_credential_source_id,proto3" json:"application_credential_source_ids,omitempty"`
EgressCredentialSourceIds []string `protobuf:"bytes,4,rep,name=egress_credential_source_ids,proto3" json:"egress_credential_source_ids,omitempty"`
}
func (x *RemoveTargetCredentialSourcesRequest) Reset() {
@@ -1828,6 +1844,13 @@ func (x *RemoveTargetCredentialSourcesRequest) GetApplicationCredentialSourceIds
return nil
}
func (x *RemoveTargetCredentialSourcesRequest) GetEgressCredentialSourceIds() []string {
if x != nil {
return x.EgressCredentialSourceIds
}
return nil
}
type RemoveTargetCredentialSourcesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -2204,7 +2227,7 @@ var file_controller_api_services_v1_target_service_proto_rawDesc = []byte{
0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x22, 0x9b, 0x01, 0x0a, 0x21, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x65, 0x6d, 0x22, 0xdf, 0x01, 0x0a, 0x21, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72,
@@ -2214,325 +2237,338 @@ var file_controller_api_services_v1_target_service_proto_rawDesc = []byte{
0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x21,
0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64,
0x73, 0x22, 0x65, 0x0a, 0x22, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x9b, 0x01, 0x0a, 0x21, 0x53, 0x65, 0x74,
0x73, 0x12, 0x42, 0x0a, 0x1c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f,
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x65, 0x0a, 0x22, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xdf, 0x01, 0x0a,
0x21, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x21,
0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64,
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x21, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x42, 0x0a, 0x1c, 0x65, 0x67,
0x72, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09,
0x52, 0x1c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x65,
0x0a, 0x22, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xe1, 0x01, 0x0a, 0x24, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18,
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x21, 0x61, 0x70, 0x70, 0x6c,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x21, 0x61, 0x70, 0x70, 0x6c,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20,
0x03, 0x28, 0x09, 0x52, 0x21, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x03, 0x28, 0x09, 0x52, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x65, 0x0a, 0x22, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04,
0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x9d, 0x01,
0x0a, 0x24, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x4b, 0x0a, 0x21, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x63, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x42, 0x0a, 0x1c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f,
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x20, 0x61, 0x70, 0x70,
0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x68, 0x0a,
0x25, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65,
0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 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,
0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0x97, 0x20, 0x0a, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31,
0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73,
0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x9a, 0x01,
0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x2e, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x92, 0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c,
0x6c, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x12, 0xaf, 0x01, 0x0a, 0x0c, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x1a, 0x12, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69,
0x6e, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xad, 0x01, 0x0a,
0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x73, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xa1, 0x01, 0x0a,
0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e,
0x12, 0xcc, 0x01, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x4d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x7a, 0x65, 0x2d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x62,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
0x69, 0x7a, 0x65, 0x73, 0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x12,
0xda, 0x01, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73,
0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74,
0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x58, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64,
0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69,
0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20,
0x74, 0x6f, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xd7, 0x01, 0x0a,
0x11, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65,
0x74, 0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1c, 0x65, 0x67, 0x72,
0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x22, 0x68, 0x0a, 0x25, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x2b, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x1d,
0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x39, 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, 0x52, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x32, 0x97, 0x20, 0x0a, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x47, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c,
0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x4c, 0x69,
0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x92,
0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x12, 0xaf, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48,
0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x55, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f,
0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x23, 0x12, 0x21, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f,
0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe4, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12,
0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x59, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a,
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x73, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f,
0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe9, 0x01,
0x0a, 0x14, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x19, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x3a,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1a, 0x12, 0x18,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65,
0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61,
0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x73, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xcc, 0x01, 0x0a,
0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73,
0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b,
0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x29,
0x12, 0x27, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20,
0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20,
0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe9, 0x01, 0x0a, 0x14, 0x53, 0x65,
0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
0x2d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x73,
0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x12, 0xda, 0x01, 0x0a, 0x11,
0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74,
0x73, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41,
0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f,
0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x58,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x68, 0x6f, 0x73,
0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e,
0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xd7, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x74,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x34,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53,
0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x82, 0xd3, 0xe4,
0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73,
0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x23, 0x12,
0x21, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53,
0x65, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x2e, 0x12, 0xe4, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f,
0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x59,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d,
0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74,
0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x48,
0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe9, 0x01, 0x0a, 0x14, 0x41, 0x64,
0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75,
0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f,
0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a,
0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x29, 0x12, 0x27, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xf3, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e,
0x61, 0x64, 0x64, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x29, 0x12, 0x27, 0x41, 0x64,
0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74,
0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe9, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x37,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f,
0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x5e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d,
0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x29, 0x12, 0x27, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x2e, 0x12, 0xf3, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2f, 0x22, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f,
0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x68, 0x6f, 0x73, 0x74,
0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65,
0x6d, 0x92, 0x41, 0x27, 0x12, 0x25, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x48, 0x6f,
0x73, 0x74, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x98, 0x02, 0x0a, 0x1c,
0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x3f, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62,
0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69,
0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x75, 0x88, 0x02, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64,
0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x6c, 0x69, 0x62, 0x72,
0x61, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41,
0x35, 0x12, 0x33, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75,
0x73, 0x65, 0x20, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x69, 0x6e,
0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0x12, 0x98, 0x02, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69,
0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x3f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x24,
0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d,
0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x27,
0x12, 0x25, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x98, 0x02, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c,
0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x3f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43,
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69,
0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x75, 0x88, 0x02, 0x01, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x63, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x35, 0x12, 0x33, 0x44, 0x65,
0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75, 0x73, 0x65, 0x20, 0x53, 0x65,
0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64,
0x2e, 0x12, 0xa7, 0x02, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72,
0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x42, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x75, 0x88, 0x02, 0x01,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x63, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65,
0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x35, 0x12, 0x33, 0x44,
0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75, 0x73, 0x65, 0x20, 0x41,
0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61,
0x64, 0x2e, 0x12, 0x98, 0x02, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
0x69, 0x65, 0x73, 0x12, 0x3f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x75, 0x88, 0x02, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x34, 0x22, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b,
0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62,
0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x35, 0x12, 0x33, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63,
0x61, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75, 0x73, 0x65, 0x20, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0x12, 0xa7, 0x02,
0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65,
0x73, 0x12, 0x42, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62,
0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7b,
0x88, 0x02, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x6c, 0x69,
0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x38, 0x12, 0x36, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x3a,
0x20, 0x75, 0x73, 0x65, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0x12, 0x87, 0x02, 0x0a, 0x1a,
0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6e,
0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7b, 0x88, 0x02, 0x01, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x37, 0x22, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x63,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
0x69, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x38, 0x12,
0x36, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x3a, 0x20, 0x75, 0x73, 0x65,
0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x69,
0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0x12, 0x87, 0x02, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x27, 0x2f,
0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a,
0x61, 0x64, 0x64, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
0x41, 0x2f, 0x12, 0x2d, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e,
0x67, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x2e, 0x12, 0x84, 0x02, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65,
0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x67, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x63, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2c, 0x12, 0x2a, 0x53, 0x65,
0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
0x6c, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x91, 0x02, 0x0a, 0x1d, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6a, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x32, 0x22, 0x27, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b,
0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69,
0x74, 0x65, 0x6d, 0x92, 0x41, 0x2f, 0x12, 0x2d, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69,
0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x84, 0x02, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x67, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x27, 0x2f, 0x76, 0x31,
0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65,
0x74, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2c,
0x12, 0x2a, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x6e,
0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x91, 0x02, 0x0a,
0x1d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x40,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f,
0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x41, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x22, 0x2a, 0x2f, 0x76, 0x31,
0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
0x92, 0x41, 0x2d, 0x12, 0x2b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x43, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e,
0x42, 0x4d, 0x5a, 0x4b, 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, 0x61, 0x70, 0x69, 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,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x22, 0x2a, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x2d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2d, 0x12,
0x2b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d,
0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x42, 0x4d, 0x5a, 0x4b,
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, 0x61, 0x70, 0x69, 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 (
+565 -6
View File
@@ -14,12 +14,503 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)
// TODO (jimlambrt 8/2020) define tests for immutable fields in the remaining
// kms tables:
// kms_oplog_key
// kms_oplog_key_version
// kms_session_key
// kms_session_key_version
func TestOplogKey_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
wrapper := db.TestWrapper(t)
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
require.NoError(t, conn.Where("1=1").Delete(kms.AllocOplogKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
new := kms.TestOplogKey(t, conn, rk.PrivateId)
tests := []struct {
name string
update *kms.OplogKey
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.OplogKey {
k := new.Clone().(*kms.OplogKey)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.OplogKey {
k := new.Clone().(*kms.OplogKey)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "root_key_id",
update: func() *kms.OplogKey {
k := new.Clone().(*kms.OplogKey)
k.RootKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"ScopeId"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.OplogKey), after.(*kms.OplogKey)))
})
}
}
func TestOplogKeyVersion_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
wrapper := db.TestWrapper(t)
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
_, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId)
dk := kms.TestOplogKey(t, conn, rk.PrivateId)
new := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oplog key"))
tests := []struct {
name string
update *kms.OplogKeyVersion
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "oplog_key_id",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.OplogKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "root_key_version_id",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.RootKeyVersionId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "version",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.Version = uint32(22)
return k
}(),
fieldMask: []string{"Version"},
},
{
name: "key",
update: func() *kms.OplogKeyVersion {
k := new.Clone().(*kms.OplogKeyVersion)
k.Key = []byte("updated key")
return k
}(),
fieldMask: []string{"CtKey"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
err = tt.update.Encrypt(context.Background(), wrapper)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.OplogKeyVersion), after.(*kms.OplogKeyVersion)))
})
}
}
func TestTokenKey_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
wrapper := db.TestWrapper(t)
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
require.NoError(t, conn.Where("1=1").Delete(kms.AllocTokenKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
new := kms.TestTokenKey(t, conn, rk.PrivateId)
tests := []struct {
name string
update *kms.TokenKey
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.TokenKey {
k := new.Clone().(*kms.TokenKey)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.TokenKey {
k := new.Clone().(*kms.TokenKey)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "root_key_id",
update: func() *kms.TokenKey {
k := new.Clone().(*kms.TokenKey)
k.RootKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"ScopeId"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.TokenKey), after.(*kms.TokenKey)))
})
}
}
func TestTokenKeyVersion_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
wrapper := db.TestWrapper(t)
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
_, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId)
dk := kms.TestTokenKey(t, conn, rk.PrivateId)
new := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("token key"))
tests := []struct {
name string
update *kms.TokenKeyVersion
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "token_key_id",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.TokenKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "root_key_version_id",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.RootKeyVersionId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "version",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.Version = uint32(22)
return k
}(),
fieldMask: []string{"Version"},
},
{
name: "key",
update: func() *kms.TokenKeyVersion {
k := new.Clone().(*kms.TokenKeyVersion)
k.Key = []byte("updated key")
return k
}(),
fieldMask: []string{"CtKey"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
err = tt.update.Encrypt(context.Background(), wrapper)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.TokenKeyVersion), after.(*kms.TokenKeyVersion)))
})
}
}
func TestSessionKey_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
wrapper := db.TestWrapper(t)
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
require.NoError(t, conn.Where("1=1").Delete(kms.AllocSessionKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
new := kms.TestSessionKey(t, conn, rk.PrivateId)
tests := []struct {
name string
update *kms.SessionKey
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.SessionKey {
k := new.Clone().(*kms.SessionKey)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.SessionKey {
k := new.Clone().(*kms.SessionKey)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "root_key_id",
update: func() *kms.SessionKey {
k := new.Clone().(*kms.SessionKey)
k.RootKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"ScopeId"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.SessionKey), after.(*kms.SessionKey)))
})
}
}
func TestSessionKeyVersion_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
wrapper := db.TestWrapper(t)
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
_, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId)
dk := kms.TestSessionKey(t, conn, rk.PrivateId)
new := kms.TestSessionKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("session key"))
tests := []struct {
name string
update *kms.SessionKeyVersion
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "Session_key_id",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.SessionKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "root_key_version_id",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.RootKeyVersionId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"RootKeyId"},
},
{
name: "version",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.Version = uint32(22)
return k
}(),
fieldMask: []string{"Version"},
},
{
name: "key",
update: func() *kms.SessionKeyVersion {
k := new.Clone().(*kms.SessionKeyVersion)
k.Key = []byte("updated key")
return k
}(),
fieldMask: []string{"CtKey"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
err = tt.update.Encrypt(context.Background(), wrapper)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.SessionKeyVersion), after.(*kms.SessionKeyVersion)))
})
}
}
func TestRootKeyVersion_ImmutableFields(t *testing.T) {
t.Parallel()
@@ -341,6 +832,74 @@ func TestDatabaseKeyVersion_ImmutableFields(t *testing.T) {
}
}
func TestOidcKey_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
ts := timestamp.Timestamp{Timestamp: &timestamppb.Timestamp{Seconds: 0, Nanos: 0}}
wrapper := db.TestWrapper(t)
org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error)
require.NoError(t, conn.Where("1=1").Delete(kms.AllocOidcKey()).Error)
rk := kms.TestRootKey(t, conn, org.PublicId)
new := kms.TestOidcKey(t, conn, rk.PrivateId)
tests := []struct {
name string
update *kms.OidcKey
fieldMask []string
}{
{
name: "private_id",
update: func() *kms.OidcKey {
k := new.Clone().(*kms.OidcKey)
k.PrivateId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"PrivateId"},
},
{
name: "create time",
update: func() *kms.OidcKey {
k := new.Clone().(*kms.OidcKey)
k.CreateTime = &ts
return k
}(),
fieldMask: []string{"CreateTime"},
},
{
name: "root_key_id",
update: func() *kms.OidcKey {
k := new.Clone().(*kms.OidcKey)
k.RootKeyId = "o_thisIsNotAValidId"
return k
}(),
fieldMask: []string{"ScopeId"},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
orig := new.Clone()
err := rw.LookupById(context.Background(), orig)
require.NoError(err)
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
after := new.Clone()
err = rw.LookupById(context.Background(), after)
require.NoError(err)
assert.True(proto.Equal(orig.(*kms.OidcKey), after.(*kms.OidcKey)))
})
}
}
func TestOidcKeyVersion_ImmutableFields(t *testing.T) {
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
-41
View File
@@ -2,9 +2,7 @@ package kms
import (
"context"
"crypto/sha256"
"fmt"
"io"
"sync"
"github.com/hashicorp/boundary/internal/db"
@@ -13,7 +11,6 @@ import (
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
"github.com/hashicorp/go-kms-wrapping/wrappers/multiwrapper"
"golang.org/x/crypto/hkdf"
)
// ExternalWrappers holds wrappers defined outside of Boundary, e.g. in its
@@ -371,41 +368,3 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r
return multi, nil
}
// DerivedReader returns a reader from which keys can be read, using the
// given wrapper, reader length limit, salt and context info. Salt and info can
// be nil.
//
// Example:
// reader, _ := NewDerivedReader(wrapper, userId, jobId)
// key := ed25519.GenerateKey(reader)
func NewDerivedReader(wrapper wrapping.Wrapper, lenLimit int64, salt, info []byte) (*io.LimitedReader, error) {
const op = "kms.NewDerivedReader"
if wrapper == nil {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing wrapper")
}
if lenLimit < 20 {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "lenLimit must be >= 20")
}
var aeadWrapper *aead.Wrapper
switch w := wrapper.(type) {
case *multiwrapper.MultiWrapper:
raw := w.WrapperForKeyID("__base__")
var ok bool
if aeadWrapper, ok = raw.(*aead.Wrapper); !ok {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "unexpected wrapper type from multiwrapper base")
}
case *aead.Wrapper:
if w.GetKeyBytes() == nil {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "aead wrapper missing bytes")
}
aeadWrapper = w
default:
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "unknown wrapper type")
}
reader := hkdf.New(sha256.New, aeadWrapper.GetKeyBytes(), salt, info)
return &io.LimitedReader{
R: reader,
N: lenLimit,
}, nil
}
-105
View File
@@ -3,19 +3,12 @@ package kms
import (
"context"
"crypto/rand"
"crypto/sha256"
"io"
"testing"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/types/scope"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
"github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/hkdf"
)
func TestKms_KeyId(t *testing.T) {
@@ -73,101 +66,3 @@ func TestKms_KeyId(t *testing.T) {
_, err = kmsCache.GetWrapper(ctx, scope.Global.String(), KeyPurposeDatabase, WithKeyId("foo"))
require.Error(err)
}
func TestNewDerivedReader(t *testing.T) {
wrapper := db.TestWrapper(t)
type args struct {
wrapper wrapping.Wrapper
lenLimit int64
salt []byte
info []byte
}
tests := []struct {
name string
args args
want *io.LimitedReader
wantErr bool
wantErrCode errors.Code
wantErrContains string
}{
{
name: "valid-with-salt",
args: args{
wrapper: wrapper,
lenLimit: 32,
info: nil,
salt: []byte("salt"),
},
want: &io.LimitedReader{
R: hkdf.New(sha256.New, wrapper.(*aead.Wrapper).GetKeyBytes(), []byte("salt"), nil),
N: 32,
},
},
{
name: "valid-with-salt-info",
args: args{
wrapper: wrapper,
lenLimit: 32,
info: []byte("info"),
salt: []byte("salt"),
},
want: &io.LimitedReader{
R: hkdf.New(sha256.New, wrapper.(*aead.Wrapper).GetKeyBytes(), []byte("salt"), []byte("info")),
N: 32,
},
},
{
name: "nil-wrapper",
args: args{
wrapper: nil,
lenLimit: 10,
info: []byte("info"),
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
wantErrContains: "missing wrapper",
},
{
name: "too-short",
args: args{
wrapper: wrapper,
lenLimit: 10,
info: []byte("info"),
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
wantErrContains: "lenLimit must be >= 20",
},
{
name: "wrapper-with-no-bytes",
args: args{
wrapper: &aead.Wrapper{},
lenLimit: 32,
info: nil,
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
wantErrContains: "missing bytes",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := NewDerivedReader(tt.args.wrapper, tt.args.lenLimit, tt.args.salt, tt.args.info)
if tt.wantErr {
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.InvalidParameter), err), "unexpected error: %s", err)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
return
}
require.NoError(err)
assert.Equal(tt.want, got)
})
}
}
+1 -1
View File
@@ -110,7 +110,7 @@ func (r *Repository) LookupDatabaseKey(ctx context.Context, privateId string, _
// repository returning a count of the number of records deleted. All options
// are ignored.
func (r *Repository) DeleteDatabaseKey(ctx context.Context, privateId string, _ ...Option) (int, error) {
const op = "kms.(Repository).LookupDatabaseKey"
const op = "kms.(Repository).DeleteDatabaseKey"
if privateId == "" {
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id")
}
+1 -1
View File
@@ -110,7 +110,7 @@ func (r *Repository) LookupOidcKey(ctx context.Context, privateId string, _ ...O
// repository returning a count of the number of records deleted. All options
// are ignored.
func (r *Repository) DeleteOidcKey(ctx context.Context, privateId string, _ ...Option) (int, error) {
const op = "kms.(Repository).LookupOidcKey"
const op = "kms.(Repository).DeleteOidcKey"
if privateId == "" {
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id")
}
+1 -1
View File
@@ -220,7 +220,7 @@ func TestOidcKeyVersion(t *testing.T, conn *db.DB, rootKeyVersionWrapper wrappin
require.NotEmpty(rootKeyVersionId)
k, err := NewOidcKeyVersion(oidcKeyId, key, rootKeyVersionId)
require.NoError(err)
id, err := newDatabaseKeyVersionId()
id, err := newOidcKeyVersionId()
require.NoError(err)
k.PrivateId = id
err = k.Encrypt(context.Background(), rootKeyVersionWrapper)
+50
View File
@@ -0,0 +1,50 @@
package crypto
import (
"crypto/sha256"
"fmt"
"io"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
"github.com/hashicorp/go-kms-wrapping/wrappers/multiwrapper"
"golang.org/x/crypto/hkdf"
)
// DerivedReader returns a reader from which keys can be read, using the
// given wrapper, reader length limit, salt and context info. Salt and info can
// be nil.
//
// Example:
// reader, _ := NewDerivedReader(wrapper, userId, jobId)
// key := ed25519.GenerateKey(reader)
func NewDerivedReader(wrapper wrapping.Wrapper, lenLimit int64, salt, info []byte) (*io.LimitedReader, error) {
const op = "crypto.NewDerivedReader"
if wrapper == nil {
return nil, fmt.Errorf("%s: missing wrapper: %w", op, ErrInvalidParameter)
}
if lenLimit < 20 {
return nil, fmt.Errorf("%s: lenLimit must be >= 20: %w", op, ErrInvalidParameter)
}
var aeadWrapper *aead.Wrapper
switch w := wrapper.(type) {
case *multiwrapper.MultiWrapper:
raw := w.WrapperForKeyID("__base__")
var ok bool
if aeadWrapper, ok = raw.(*aead.Wrapper); !ok {
return nil, fmt.Errorf("%s: unexpected wrapper type from multiwrapper base: %w", op, ErrInvalidParameter)
}
case *aead.Wrapper:
if w.GetKeyBytes() == nil {
return nil, fmt.Errorf("%s: aead wrapper missing bytes: %w", op, ErrInvalidParameter)
}
aeadWrapper = w
default:
return nil, fmt.Errorf("%s: unknown wrapper type: %w", op, ErrInvalidParameter)
}
reader := hkdf.New(sha256.New, aeadWrapper.GetKeyBytes(), salt, info)
return &io.LimitedReader{
R: reader,
N: lenLimit,
}, nil
}
+111
View File
@@ -0,0 +1,111 @@
package crypto
import (
"crypto/sha256"
"io"
"testing"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/hkdf"
)
func TestNewDerivedReader(t *testing.T) {
wrapper := TestWrapper(t)
type args struct {
wrapper wrapping.Wrapper
lenLimit int64
salt []byte
info []byte
}
tests := []struct {
name string
args args
want *io.LimitedReader
wantErr bool
wantErrCode error
wantErrContains string
}{
{
name: "valid-with-salt",
args: args{
wrapper: wrapper,
lenLimit: 32,
info: nil,
salt: []byte("salt"),
},
want: &io.LimitedReader{
R: hkdf.New(sha256.New, wrapper.(*aead.Wrapper).GetKeyBytes(), []byte("salt"), nil),
N: 32,
},
},
{
name: "valid-with-salt-info",
args: args{
wrapper: wrapper,
lenLimit: 32,
info: []byte("info"),
salt: []byte("salt"),
},
want: &io.LimitedReader{
R: hkdf.New(sha256.New, wrapper.(*aead.Wrapper).GetKeyBytes(), []byte("salt"), []byte("info")),
N: 32,
},
},
{
name: "nil-wrapper",
args: args{
wrapper: nil,
lenLimit: 10,
info: []byte("info"),
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: ErrInvalidParameter,
wantErrContains: "missing wrapper",
},
{
name: "too-short",
args: args{
wrapper: wrapper,
lenLimit: 10,
info: []byte("info"),
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: ErrInvalidParameter,
wantErrContains: "lenLimit must be >= 20",
},
{
name: "wrapper-with-no-bytes",
args: args{
wrapper: &aead.Wrapper{},
lenLimit: 32,
info: nil,
salt: []byte("salt"),
},
wantErr: true,
wantErrCode: ErrInvalidParameter,
wantErrContains: "missing bytes",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := NewDerivedReader(tt.args.wrapper, tt.args.lenLimit, tt.args.salt, tt.args.info)
if tt.wantErr {
require.Error(err)
assert.ErrorIsf(err, tt.wantErrCode, "unexpected error: %s", err)
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
return
}
require.NoError(err)
assert.Equal(tt.want, got)
})
}
}
+9
View File
@@ -0,0 +1,9 @@
package crypto
import (
"errors"
)
var (
ErrInvalidParameter = errors.New("Invalid parameter")
)
+94
View File
@@ -0,0 +1,94 @@
package crypto
import (
"context"
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
wrapping "github.com/hashicorp/go-kms-wrapping"
"golang.org/x/crypto/blake2b"
)
// HmacSha256WithPrk will HmacSha256 using the provided prk. See HmacSha256 for
// options supported.
func HmacSha256WithPrk(ctx context.Context, data, prk []byte, opt ...Option) (string, error) {
opt = append(opt, WithPrk(prk))
return HmacSha256(ctx, data, nil, nil, nil, opt...)
}
// HmacSha256 the provided data. Supports WithPrefix, WithEd25519 and WithPrk
// options. WithEd25519 is a "legacy" way to complete this operation and should
// not be used in new operations unless backward compatibility is needed. The
// WithPrefix option will prepend the prefix to the hmac-sha256 value.
func HmacSha256(ctx context.Context, data []byte, cipher wrapping.Wrapper, salt, info []byte, opt ...Option) (string, error) {
const op = "crypto.HmacSha256"
opts, err := getOpts(opt...)
if err != nil {
return "", fmt.Errorf("%s: unable to get options: %w", op, err)
}
if data == nil {
return "", fmt.Errorf("%s: missing data: %w", op, ErrInvalidParameter)
}
if cipher == nil && opts.withPrk == nil {
return "", fmt.Errorf("%s: you must specify either a wrapper or prk: %w", op, ErrInvalidParameter)
}
if cipher != nil && opts.withPrk != nil {
return "", fmt.Errorf("%s: you cannot specify both a wrapper or prk: %w", op, ErrInvalidParameter)
}
if opts.withEd25519 && opts.withPrk != nil {
return "", fmt.Errorf("%s: you cannot specify both ed25519 and a prk: %w", op, ErrInvalidParameter)
}
var key [32]byte
switch {
case opts.withPrk != nil:
key = blake2b.Sum256(opts.withPrk)
case opts.withEd25519:
reader, err := NewDerivedReader(cipher, 32, salt, info)
if err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
edKey, _, err := ed25519.GenerateKey(reader)
if err != nil {
return "", fmt.Errorf("%s: unable to generate derived key: %w", op, ErrInvalidParameter)
}
n := copy(key[:], edKey)
if n != 32 {
return "", fmt.Errorf("%s: expected to copy 32 bytes and got: %d", op, n)
}
default:
reader, err := NewDerivedReader(cipher, 32, salt, info)
if err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
readerKey := make([]byte, 32)
n, err := io.ReadFull(reader, readerKey)
if err != nil {
return "", fmt.Errorf("%s: %w", op, err)
}
if n != 32 {
return "", fmt.Errorf("%s: expected to read 32 bytes and got: %d", op, n)
}
key = blake2b.Sum256(readerKey)
}
mac := hmac.New(sha256.New, key[:])
_, _ = mac.Write(data)
hmac := mac.Sum(nil)
var hmacString string
switch opts.withBase64Encoding {
case true:
hmacString = base64.RawURLEncoding.EncodeToString(hmac)
case false:
hmacString = string(hmac)
}
if opts.withPrefix != "" {
return opts.withPrefix + hmacString, nil
}
return hmacString, nil
}
+168
View File
@@ -0,0 +1,168 @@
package crypto
import (
"context"
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"io"
"testing"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/blake2b"
)
func Test_HmacSha256(t *testing.T) {
testCtx := context.Background()
testWrapper := TestWrapper(t)
tests := []struct {
name string
data []byte
wrapper wrapping.Wrapper
salt []byte
info []byte
opts []Option
wantHmac string
wantErr bool
wantErrIs error
}{
{
name: "missing data",
wrapper: testWrapper,
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "missing wrapper",
data: []byte("test"),
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "prk-and-ed25519",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrk([]byte("prk")), WithEd25519()},
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "prk-and-wrapper",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrk([]byte("prk")), WithEd25519()},
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "blake2b-with-prefix",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrefix("prefix:")},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:")),
},
{
name: "blake2b-with-prefix-with-bas64",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrefix("prefix:"), WithBase64Encoding()},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:"), WithBase64Encoding()),
},
{
name: "with-prk",
data: []byte("test"),
opts: []Option{WithPrk([]byte("prk-0123456789012345678901234567890"))},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrk([]byte("prk-0123456789012345678901234567890"))),
},
{
name: "withEd25519",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithEd25519()},
wantHmac: testWithEd25519(t, []byte("test"), testWrapper, nil, nil),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
hm, err := HmacSha256(testCtx, tt.data, tt.wrapper, tt.salt, tt.info, tt.opts...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
assert.ErrorIs(err, tt.wantErrIs)
}
return
}
require.NoError(err)
assert.Equal(tt.wantHmac, hm)
})
}
t.Run("HmacSha256WithPrk", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
hm, err := HmacSha256WithPrk(testCtx, []byte("test"), []byte("prk-0123456789012345678901234567890"))
require.NoError(err)
want := testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrk([]byte("prk-0123456789012345678901234567890")))
assert.Equal(want, hm)
})
}
func testWithEd25519(t *testing.T, data []byte, w wrapping.Wrapper, salt, info []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
reader, err := NewDerivedReader(w, 32, salt, info)
require.NoError(err)
edKey, _, err := ed25519.GenerateKey(reader)
require.NoError(err)
var key [32]byte
n := copy(key[:], edKey)
require.Equal(n, 32)
return testHmac(t, key[:], data, opt...)
}
func testWithBlake2b(t *testing.T, data []byte, w wrapping.Wrapper, salt, info []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
require.NotNil(data)
require.NotNil(w)
opts, err := getOpts(opt...)
require.NoError(err)
var key [32]byte
switch {
case opts.withPrk != nil:
key = blake2b.Sum256(opts.withPrk)
default:
reader, err := NewDerivedReader(w, 32, salt, info)
require.NoError(err)
readerKey := make([]byte, 32)
n, err := io.ReadFull(reader, readerKey)
require.NoError(err)
require.Equal(n, 32)
key = blake2b.Sum256(readerKey)
}
return testHmac(t, key[:], data, opt...)
}
func testHmac(t *testing.T, key, data []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
mac := hmac.New(sha256.New, key)
_, _ = mac.Write(data)
hmac := mac.Sum(nil)
var hmacString string
opts, err := getOpts(opt...)
require.NoError(err)
switch opts.withBase64Encoding {
case true:
hmacString = base64.RawURLEncoding.EncodeToString(hmac)
case false:
hmacString = string(hmac)
}
if opts.withPrefix != "" {
return opts.withPrefix + hmacString
}
return hmacString
}
+63
View File
@@ -0,0 +1,63 @@
package crypto
// getOpts - iterate the inbound Options and return a struct.
func getOpts(opt ...Option) (*options, error) {
opts := getDefaultOptions()
for _, o := range opt {
if o != nil {
if err := o(opts); err != nil {
return nil, err
}
}
}
return opts, nil
}
// Option - how Options are passed as arguments.
type Option func(*options) error
// options = how options are represented
type options struct {
withPrefix string
withPrk []byte
withEd25519 bool
withBase64Encoding bool
}
func getDefaultOptions() *options {
return &options{}
}
// WithPrefix allows an optional prefix to be specified for the data returned
func WithPrefix(prefix string) Option {
return func(o *options) error {
o.withPrefix = prefix
return nil
}
}
// WithPrk allows an optional PRK (pseudorandom key) to be specified for an
// operation. If you're using this option with HmacSha256, you might consider
// using HmacSha256WithPrk instead.
func WithPrk(prk []byte) Option {
return func(o *options) error {
o.withPrk = prk
return nil
}
}
// WithEd25519 allows an optional request to use ed25519 during the operation
func WithEd25519() Option {
return func(o *options) error {
o.withEd25519 = true
return nil
}
}
// WithBase64Encoding allows an optional request to base64 encode the data returned
func WithBase64Encoding() Option {
return func(o *options) error {
o.withBase64Encoding = true
return nil
}
}
+45
View File
@@ -0,0 +1,45 @@
package crypto
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Test_GetOpts provides unit tests for GetOpts and all the options
func Test_GetOpts(t *testing.T) {
t.Parallel()
t.Run("WithPrefix", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
opts, err := getOpts(WithPrefix("test"))
require.NoError(err)
testOpts := getDefaultOptions()
testOpts.withPrefix = "test"
assert.Equal(opts, testOpts)
})
t.Run("WithPrk", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
opts, err := getOpts(WithPrk([]byte("test")))
require.NoError(err)
testOpts := getDefaultOptions()
testOpts.withPrk = []byte("test")
assert.Equal(opts, testOpts)
})
t.Run("WithEd25519", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
opts, err := getOpts(WithEd25519())
require.NoError(err)
testOpts := getDefaultOptions()
testOpts.withEd25519 = true
assert.Equal(opts, testOpts)
})
t.Run("WithBase64Encoding", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
opts, err := getOpts(WithBase64Encoding())
require.NoError(err)
testOpts := getDefaultOptions()
testOpts.withBase64Encoding = true
assert.Equal(opts, testOpts)
})
}
+33
View File
@@ -0,0 +1,33 @@
package crypto
import (
"crypto/rand"
"encoding/base64"
"testing"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
)
// TestWrapper initializes an AEAD wrapping.Wrapper for testing
func TestWrapper(t *testing.T) wrapping.Wrapper {
rootKey := make([]byte, 32)
n, err := rand.Read(rootKey)
if err != nil {
t.Fatal(err)
}
if n != 32 {
t.Fatal(n)
}
root := aead.NewWrapper(nil)
_, err = root.SetConfig(map[string]string{
"key_id": base64.StdEncoding.EncodeToString(rootKey),
})
if err != nil {
t.Fatal(err)
}
if err := root.SetAESGCMKeyBytes(rootKey); err != nil {
t.Fatal(err)
}
return root
}
+1 -1
View File
@@ -662,7 +662,7 @@ func Test_WriteAudit(t *testing.T) {
AuthAccountId: "test_auth_account_id",
},
GrantsInfo: &event.GrantsInfo{
Grants: []event.GrantsPair{
Grants: []event.Grant{
{
Grant: "test_grant",
ScopeId: "test_grant_scope_id",
+9 -7
View File
@@ -25,20 +25,22 @@ type UserInfo struct {
}
type GrantsInfo struct {
Grants []GrantsPair `json:"grants_pair,omitempty"`
Grants []Grant `json:"grants,omitempty"`
}
type GrantsPair struct {
type Grant struct {
Grant string `json:"grant,omitempty" class:"public"`
ScopeId string `json:"scope_id,omitempty" class:"public"`
RoleId string `json:"role_id,omitempty" class:"public"`
}
type Auth struct {
AuthTokenId string `json:"auth_token_id" class:"public"`
UserInfo *UserInfo `json:"user_info,omitempty"` // boundary field
GrantsInfo *GrantsInfo `json:"grants_info,omitempty"`
UserEmail string `json:"email,omitempty" class:"sensitive"`
UserName string `json:"name,omitempty" class:"sensitive"`
DisabledAuthEntirely *bool `json:"disabled_auth_entirely,omitempty" class:"public"`
AuthTokenId string `json:"auth_token_id" class:"public"`
UserInfo *UserInfo `json:"user_info,omitempty"` // boundary field
GrantsInfo *GrantsInfo `json:"grants_info,omitempty"`
UserEmail string `json:"email,omitempty" class:"sensitive"`
UserName string `json:"name,omitempty" class:"sensitive"`
}
type Request struct {
@@ -143,11 +143,10 @@ message Target {
// Output only. The application credential sources associated with this Target.
repeated CredentialSource application_credential_sources = 410 [json_name="application_credential_sources"];
// TODO: Uncomment when we suport more purposes beyond application
// // Output only. The egress credential libraries associated with this Target.
// repeated CredentialLibrary egress_credential_libraries = 190 [json_name="egress_credential_libraries"];
// // Output only. The credential libraries associated with this Target.
// repeated CredentialLibrary ingress_credential_libraries = 200 [json_name="ingress_credential_libraries"];
// Output only. The IDs of the egress credential source ids associated with this Target.
repeated string egress_credential_source_ids = 500 [json_name="egress_credential_source_ids"];
// Output only. The egress credential sources associated with this Target.
repeated CredentialSource egress_credential_sources = 510 [json_name="egress_credential_sources"];
// The attributes that are applicable for the specific Target.
google.protobuf.Struct attributes = 200 [(custom_options.v1.generate_sdk_option) = true];
@@ -475,21 +475,22 @@ message AddTargetCredentialSourcesRequest {
// The mutation will fail if the version does not match the latest known good version.
uint32 version = 2;
repeated string application_credential_source_ids = 3 [json_name="application_credential_source_ids"];
repeated string egress_credential_source_ids = 4 [json_name="egress_credential_source_ids"];
}
message AddTargetCredentialSourcesResponse {
api.resources.targets.v1.Target item = 1;
}
// Sets the values for application_credential_source_ids. If any
// credential_source_id field that is not set in the request will result in
// those fields being cleared.
// Sets the values for credential sources. Any credential_source_id field that
// is not set in the request will result in those fields being cleared.
message SetTargetCredentialSourcesRequest {
string id = 1;
// Version is used to ensure this resource has not changed.
// The mutation will fail if the version does not match the latest known good version.
uint32 version = 2;
repeated string application_credential_source_ids = 3 [json_name="application_credential_source_ids"];
repeated string egress_credential_source_ids = 4 [json_name="egress_credential_source_ids"];
}
message SetTargetCredentialSourcesResponse {
@@ -502,6 +503,7 @@ message RemoveTargetCredentialSourcesRequest {
// The mutation will fail if the version does not match the latest known good version.
uint32 version = 2;
repeated string application_credential_source_ids = 3 [json_name="application_credential_source_id"];
repeated string egress_credential_source_ids = 4 [json_name="egress_credential_source_ids"];
}
message RemoveTargetCredentialSourcesResponse {
@@ -118,4 +118,27 @@ message StoreTestScooter {
// @inject_tag: `gorm:"default:null"`
int32 mpg = 7;
}
// StoreTestAccessory used in the db tests only and provides a gorm resource with
// an id that's not a private or public id
message StoreTestAccessory {
// @inject_tag: gorm:"primary_key"
uint32 accessory_id = 1;
// @inject_tag: `gorm:"default:not_null"`
string description = 2;
}
// StoreTestScooterAccessory used in the db tests only and provides a gorm
// resource with multiple pks
message StoreTestScooterAccessory {
// @inject_tag: gorm:"primary_key"
uint32 accessory_id = 1;
// @inject_tag: gorm:"primary_key"
uint32 scooter_id = 2;
// @inject_tag: `gorm:"default:null"`
string review = 3;
}
@@ -0,0 +1,73 @@
syntax = "proto3";
package controller.storage.target.targettest.store.v1;
option go_package = "github.com/hashicorp/boundary/internal/target/targettest/store;store";
import "controller/storage/timestamp/v1/timestamp.proto";
import "controller/custom_options/v1/options.proto";
message Target {
// public_id is used to access the targettest.Target via an API
// @inject_tag: gorm:"primary_key"
string public_id = 10;
// scope id for the targettest.Target
// @inject_tag: `gorm:"default:null"`
string scope_id = 20;
// name is the optional friendly name used to
// access the targettest.Target via an API
// @inject_tag: `gorm:"default:null"`
string name = 30
[(custom_options.v1.mask_mapping) = { this: "name" that: "name" }];
// description of the targettest.Target
// @inject_tag: `gorm:"default:null"`
string description = 40 [(custom_options.v1.mask_mapping) = {
this: "description"
that: "description"
}];
// create_time from the RDBMS
// @inject_tag: `gorm:"default:current_timestamp"`
timestamp.v1.Timestamp create_time = 50;
// update_time from the RDBMS
// @inject_tag: `gorm:"default:current_timestamp"`
timestamp.v1.Timestamp update_time = 60;
// version allows optimistic locking of the targettest.Target when modifying the
// targettest.Target
// @inject_tag: `gorm:"default:null"`
uint32 version = 70;
// default port of the targettest.Target
// @inject_tag: `gorm:"default:null"`
uint32 default_port = 80 [(custom_options.v1.mask_mapping) = {
this: "DefaultPort"
that: "attributes.default_port"
}];
// Maximum total lifetime of a created session, in seconds
// @inject_tag: `gorm:"default:null"`
uint32 session_max_seconds = 100 [(custom_options.v1.mask_mapping) = {
this: "SessionMaxSeconds"
that: "session_max_seconds"
}];
// Maximum number of connections in a session
// @inject_tag: `gorm:"default:null"`
int32 session_connection_limit = 110 [(custom_options.v1.mask_mapping) = {
this: "SessionConnectionLimit"
that: "session_connection_limit"
}];
// A boolean expression that allows filtering the workers that can handle a session
// @inject_tag: `gorm:"default:null"`
string worker_filter = 120 [(custom_options.v1.mask_mapping) = {
this: "WorkerFilter"
that: "worker_filter"
}];
}
+55 -11
View File
@@ -140,6 +140,9 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
v.ctx = ctx
ea := &event.Auth{}
defer event.WriteAudit(ctx, op, event.WithAuth(ea))
opts := getOpts(opt...)
ret.Scope = new(scopes.ScopeInfo)
@@ -160,6 +163,8 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
// In tests we often simply disable auth so we can test the service handlers
// without fuss
if v.requestInfo.DisableAuthEntirely {
yes := true
ea.DisabledAuthEntirely = &yes
const op = "auth.(disabled).lookupScope"
ret.Scope.Id = v.requestInfo.ScopeIdOverride
if ret.Scope.Id == "" {
@@ -205,6 +210,7 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
if reqInfo != nil {
reqInfo.UserId = ret.UserId
}
ea.UserInfo = &event.UserInfo{UserId: ret.UserId}
ret.Error = nil
return
}
@@ -226,8 +232,10 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
}
var authResults perms.ACLResults
var grantTuples []perms.GrantTuple
var accountId, userName, userEmail string
var err error
authResults, ret.UserId, ret.Scope, v.acl, err = v.performAuthCheck(ctx)
authResults, ret.UserId, accountId, userName, userEmail, ret.Scope, v.acl, grantTuples, err = v.performAuthCheck(ctx)
if err != nil {
event.WriteError(ctx, op, err, event.WithInfoMsg("error performing authn/authz check"))
return
@@ -262,10 +270,31 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
if ret.UserId == AnonymousUserId {
ret.Error = handlers.UnauthenticatedError()
}
ea.UserInfo = &event.UserInfo{
UserId: ret.UserId,
}
return
}
}
grants := make([]event.Grant, 0, len(grantTuples))
for _, g := range grantTuples {
grants = append(grants, event.Grant{
Grant: g.Grant,
RoleId: g.RoleId,
ScopeId: g.ScopeId,
})
}
ea.UserInfo = &event.UserInfo{
UserId: ret.UserId,
AuthAccountId: accountId,
}
ea.GrantsInfo = &event.GrantsInfo{
Grants: grants,
}
ea.UserName = userName
ea.UserEmail = userEmail
if reqInfo != nil {
reqInfo.UserId = ret.UserId
reqInfo.OutputFields = authResults.OutputFields
@@ -401,15 +430,23 @@ func (v *verifier) decryptToken(ctx context.Context) {
}
}
func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLResults, userId string, scopeInfo *scopes.ScopeInfo, retAcl perms.ACL, retErr error) {
func (v verifier) performAuthCheck(ctx context.Context) (
aclResults perms.ACLResults,
userId string,
accountId string,
userName string,
userEmail string,
scopeInfo *scopes.ScopeInfo,
retAcl perms.ACL,
grantTuples []perms.GrantTuple,
retErr error) {
const op = "auth.(verifier).performAuthCheck"
// Ensure we return an error by default if we forget to set this somewhere
retErr = errors.NewDeprecated(errors.Unknown, op, "default auth error", errors.WithoutEvent())
retErr = errors.New(ctx, errors.Unknown, op, "default auth error", errors.WithoutEvent())
// Make the linter happy
_ = retErr
scopeInfo = new(scopes.ScopeInfo)
userId = AnonymousUserId
var accountId string
// Validate the token and fetch the corresponding user ID
switch v.requestInfo.TokenFormat {
@@ -428,7 +465,7 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
}
tokenRepo, err := v.authTokenRepoFn()
if err != nil {
retErr = errors.WrapDeprecated(err, op)
retErr = errors.Wrap(ctx, err, op)
return
}
at, err := tokenRepo.ValidateToken(v.ctx, v.requestInfo.PublicId, v.requestInfo.Token)
@@ -451,10 +488,18 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
iamRepo, err := v.iamRepoFn()
if err != nil {
retErr = errors.WrapDeprecated(err, op, errors.WithMsg("failed to get iam repo"))
retErr = errors.Wrap(ctx, err, op, errors.WithMsg("failed to get iam repo"))
return
}
u, _, err := iamRepo.LookupUser(ctx, userId)
if err != nil {
retErr = errors.Wrap(ctx, err, op, errors.WithMsg("failed to lookup user"))
return
}
userEmail = u.Email
userName = u.FullName
// Look up scope details to return. We can skip a lookup when using the
// global scope
switch v.res.ScopeId {
@@ -470,11 +515,11 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
default:
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
if err != nil {
retErr = errors.WrapDeprecated(err, op)
retErr = errors.Wrap(ctx, err, op)
return
}
if scp == nil {
retErr = errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprint("non-existent scope $q", v.res.ScopeId))
retErr = errors.New(ctx, errors.InvalidParameter, op, fmt.Sprint("non-existent scope $q", v.res.ScopeId))
return
}
scopeInfo = &scopes.ScopeInfo{
@@ -495,13 +540,12 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
}
var parsedGrants []perms.Grant
var grantTuples []perms.GrantTuple
// Fetch and parse grants for this user ID (which may include grants for
// u_anon and u_auth)
grantTuples, err = iamRepo.GrantsForUser(v.ctx, userId)
if err != nil {
retErr = errors.WrapDeprecated(err, op)
retErr = errors.Wrap(ctx, err, op)
return
}
parsedGrants = make([]perms.Grant, 0, len(grantTuples))
@@ -516,7 +560,7 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
perms.WithAccountId(accountId),
perms.WithSkipFinalValidation(true))
if err != nil {
retErr = errors.WrapDeprecated(err, op, errors.WithMsg(fmt.Sprintf("failed to parse grant %#v", pair.Grant)))
retErr = errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed to parse grant %#v", pair.Grant)))
return
}
parsedGrants = append(parsedGrants, parsed)
@@ -5,6 +5,8 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"sync"
"testing"
"github.com/hashicorp/boundary/internal/authtoken"
@@ -12,8 +14,12 @@ import (
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/observability/event"
"github.com/hashicorp/boundary/internal/servers"
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
"github.com/hashicorp/boundary/internal/tests/api"
"github.com/hashicorp/eventlogger/filters/encrypt"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -132,3 +138,125 @@ func TestAuthTokenAuthenticator(t *testing.T) {
})
}
}
func TestVerify_AuditEvent(t *testing.T) {
// this cannot run in parallel because it relies on envvar
// globals.BOUNDARY_DEVELOPER_ENABLE_EVENTS
event.TestEnableEventing(t, true)
eventConfig := event.TestEventerConfig(t, "Test_Verify", event.TestWithAuditSink(t))
testLock := &sync.Mutex{}
testLogger := hclog.New(&hclog.LoggerOptions{
Mutex: testLock,
Name: "test",
})
require.NoError(t, event.InitSysEventer(testLogger, testLock, "Test_Verify", event.WithEventerConfig(&eventConfig.EventerConfig)))
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
testKms := kms.TestKms(t, conn, wrapper)
tokenRepo, err := authtoken.NewRepository(rw, rw, testKms)
require.NoError(t, err)
iamRepo := iam.TestRepo(t, conn, wrapper)
tokenRepoFn := func() (*authtoken.Repository, error) {
return tokenRepo, nil
}
iamRepoFn := func() (*iam.Repository, error) {
return iamRepo, nil
}
serversRepoFn := func() (*servers.Repository, error) {
return servers.NewRepository(rw, rw, testKms)
}
o, _ := iam.TestScopes(t, iamRepo)
at := authtoken.TestAuthToken(t, conn, testKms, o.GetPublicId())
encToken, err := authtoken.EncryptToken(context.Background(), testKms, o.GetPublicId(), at.GetPublicId(), at.GetToken())
require.NoError(t, err)
tokValue := at.GetPublicId() + "_" + encToken
jsCookieVal, httpCookieVal := tokValue[:len(tokValue)/2], tokValue[len(tokValue)/2:]
tests := []struct {
name string
headers map[string]string
cookies []http.Cookie
opt []Option
disableAuth bool
wantResults VerifyResults
wantAuthAuditData bool
wantUserId string
}{
{
name: "bearer-token",
headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", tokValue)},
opt: []Option{WithScopeId(o.PublicId)},
wantAuthAuditData: true,
wantUserId: at.IamUserId,
},
{
name: "split-cookie-token",
cookies: []http.Cookie{
{Name: handlers.HttpOnlyCookieName, Value: httpCookieVal},
{Name: handlers.JsVisibleCookieName, Value: jsCookieVal},
},
opt: []Option{WithScopeId(o.PublicId)},
wantAuthAuditData: true,
wantUserId: at.IamUserId,
},
{
name: "no-auth-data",
opt: []Option{WithScopeId(o.PublicId)},
wantAuthAuditData: true,
wantUserId: "u_anon",
},
{
name: "disable-auth",
opt: []Option{WithScopeId(o.PublicId)},
disableAuth: true,
wantAuthAuditData: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
req := httptest.NewRequest("GET", "http://127.0.0.1/v1/scopes/o_1", nil)
for k, v := range tt.headers {
req.Header.Set(k, v)
}
for _, c := range tt.cookies {
req.AddCookie(&c)
}
// Add values for authn/authz checking
requestInfo := authpb.RequestInfo{
Path: req.URL.Path,
Method: req.Method,
DisableAuthEntirely: tt.disableAuth,
}
requestInfo.PublicId, requestInfo.EncryptedToken, requestInfo.TokenFormat = GetTokenFromRequest(context.TODO(), testKms, req)
ctx := NewVerifierContext(context.Background(), iamRepoFn, tokenRepoFn, serversRepoFn, testKms, &requestInfo)
_ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls
_ = Verify(ctx, tt.opt...)
got := api.CloudEventFromFile(t, eventConfig.AuditEvents.Name())
if tt.wantAuthAuditData {
auth, ok := got.Data.(map[string]interface{})["auth"].(map[string]interface{})
require.True(ok)
assert.Equal(encrypt.RedactedData, auth["email"])
assert.Equal(encrypt.RedactedData, auth["name"])
if tt.disableAuth {
assert.Equal(true, auth["disabled_auth_entirely"])
}
if tt.wantUserId != "" {
userInfo, ok := auth["user_info"].(map[string]interface{})
require.True(ok)
assert.Equal(tt.wantUserId, userInfo["id"])
}
}
})
}
}
@@ -592,7 +592,7 @@ func (s Service) AddTargetCredentialLibraries(ctx context.Context, req *pbs.AddT
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
if err != nil {
return nil, err
}
@@ -630,7 +630,7 @@ func (s Service) SetTargetCredentialLibraries(ctx context.Context, req *pbs.SetT
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
if err != nil {
return nil, err
}
@@ -668,7 +668,7 @@ func (s Service) RemoveTargetCredentialLibraries(ctx context.Context, req *pbs.R
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
if err != nil {
return nil, err
}
@@ -706,7 +706,7 @@ func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTar
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -744,7 +744,7 @@ func (s Service) SetTargetCredentialSources(ctx context.Context, req *pbs.SetTar
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -782,7 +782,7 @@ func (s Service) RemoveTargetCredentialSources(ctx context.Context, req *pbs.Rem
if authResults.Error != nil {
return nil, authResults.Error
}
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
if err != nil {
return nil, err
}
@@ -1352,12 +1352,17 @@ func (s Service) removeHostSourcesInRepo(ctx context.Context, targetId string, h
return out, hs, cl, nil
}
func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
repo, err := s.repoFn()
if err != nil {
return nil, nil, nil, err
}
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
if err != nil {
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
}
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, credLibs)
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to add credential sources to target: %v.", err)
@@ -1368,13 +1373,19 @@ func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string
return out, hs, credSources, nil
}
func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
const op = "targets.(Service).setCredentialSourcesInRepo"
repo, err := s.repoFn()
if err != nil {
return nil, nil, nil, err
}
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
if err != nil {
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
}
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, credLibs)
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
@@ -1390,13 +1401,18 @@ func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string
return out, hs, credSources, nil
}
func (s Service) removeCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
func (s Service) removeCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
const op = "targets.(Service).removeCredentialSourcesInRepo"
repo, err := s.repoFn()
if err != nil {
return nil, nil, nil, err
}
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
if err != nil {
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
}
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, credLibs)
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to remove credential sources from target: %v.", err)
@@ -1917,8 +1933,9 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ
if req.GetVersion() == 0 {
badFields[globals.VersionField] = "Required field."
}
if len(req.GetApplicationCredentialSourceIds()) == 0 {
badFields[globals.ApplicationCredentialSourceIdsField] = "Must be non-empty."
if len(req.GetApplicationCredentialSourceIds())+len(req.GetEgressCredentialSourceIds()) == 0 {
badFields[globals.ApplicationCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
}
for _, cl := range req.GetApplicationCredentialSourceIds() {
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
@@ -1926,6 +1943,12 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ
break
}
}
for _, cl := range req.GetEgressCredentialSourceIds() {
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
break
}
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
@@ -1946,6 +1969,12 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ
break
}
}
for _, cl := range req.GetEgressCredentialSourceIds() {
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
break
}
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
@@ -1960,8 +1989,9 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc
if req.GetVersion() == 0 {
badFields[globals.VersionField] = "Required field."
}
if len(req.GetApplicationCredentialSourceIds()) == 0 {
badFields[globals.ApplicationCredentialLibraryIdsField] = "Must be non-empty."
if len(req.GetApplicationCredentialSourceIds())+len(req.GetEgressCredentialSourceIds()) == 0 {
badFields[globals.ApplicationCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
}
for _, cl := range req.GetApplicationCredentialSourceIds() {
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
@@ -1969,6 +1999,12 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc
break
}
}
for _, cl := range req.GetEgressCredentialSourceIds() {
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
break
}
}
if len(badFields) > 0 {
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
}
@@ -2015,3 +2051,23 @@ func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error {
}
return nil
}
func createCredLibs(targetId string, applicationIds, ingressIds, egressIds []string) ([]*target.CredentialLibrary, error) {
credLibs := make([]*target.CredentialLibrary, 0, len(applicationIds)+len(ingressIds)+len(egressIds))
byPurpose := map[credential.Purpose][]string{
credential.ApplicationPurpose: strutil.RemoveDuplicates(applicationIds, false),
credential.IngressPurpose: strutil.RemoveDuplicates(ingressIds, false),
credential.EgressPurpose: strutil.RemoveDuplicates(egressIds, false),
}
for purpose, ids := range byPurpose {
for _, id := range ids {
l, err := target.NewCredentialLibrary(targetId, id, purpose)
if err != nil {
return nil, err
}
credLibs = append(credLibs, l)
}
}
return credLibs, nil
}
@@ -14,6 +14,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/credential/vault"
"github.com/hashicorp/boundary/internal/db"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
@@ -293,7 +294,16 @@ func TestList(t *testing.T) {
return
}
require.NoError(gErr)
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListTargets(%q) scope %q, got response %q, wanted %q", tc.name, tc.req.GetScopeId(), got, tc.res)
assert.Equal(len(tc.res.Items), len(got.Items))
wantById := make(map[string]*pb.Target, len(tc.res.Items))
for _, t := range tc.res.Items {
wantById[t.Id] = t
}
for _, t := range got.Items {
want, ok := wantById[t.Id]
assert.True(ok, "Got unexpected target with id: %s", t.Id)
assert.Empty(cmp.Diff(t, want, protocmp.Transform()), "got %v, wanted %v", t, want)
}
// Test with anon user
got, gErr = s.ListTargets(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId(), auth.WithUserId(auth.AnonymousUserId)), tc.req)
@@ -1806,13 +1816,13 @@ func TestAddTargetLibraries(t *testing.T) {
},
{
name: "Add library on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
addLibraries: []string{cls[1].GetPublicId()},
resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
},
{
name: "Add duplicated libraries on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
addLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
},
@@ -1942,19 +1952,19 @@ func TestSetTargetLibraries(t *testing.T) {
},
{
name: "Set on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setLibraries: []string{cls[1].GetPublicId()},
resultLibraryIds: []string{cls[1].GetPublicId()},
},
{
name: "Set duplicate libraries on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
resultLibraryIds: []string{cls[1].GetPublicId()},
},
{
name: "Set empty on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setLibraries: []string{},
resultLibraryIds: nil,
},
@@ -2068,13 +2078,13 @@ func TestRemoveTargetLibraries(t *testing.T) {
},
{
name: "Remove 1 of 2 libraries",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeLibs: []string{cls[1].GetPublicId()},
resultLibIds: []string{cls[0].GetPublicId()},
},
{
name: "Remove 1 duplicate set of 2 libraries",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeLibs: []string{
cls[1].GetPublicId(), cls[1].GetPublicId(),
},
@@ -2082,7 +2092,7 @@ func TestRemoveTargetLibraries(t *testing.T) {
},
{
name: "Remove all libraries from target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeLibs: []string{
cls[0].GetPublicId(), cls[1].GetPublicId(),
},
@@ -2203,13 +2213,13 @@ func TestAddTargetSources(t *testing.T) {
},
{
name: "Add source on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
addSources: []string{cls[1].GetPublicId()},
resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
},
{
name: "Add duplicated sources on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
addSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
},
@@ -2339,19 +2349,19 @@ func TestSetTargetCredentialSources(t *testing.T) {
},
{
name: "Set on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setCredentialSources: []string{cls[1].GetPublicId()},
resultCredentialSourceIds: []string{cls[1].GetPublicId()},
},
{
name: "Set duplicate sources on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setCredentialSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
resultCredentialSourceIds: []string{cls[1].GetPublicId()},
},
{
name: "Set empty on populated target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
setCredentialSources: []string{},
resultCredentialSourceIds: nil,
},
@@ -2465,13 +2475,13 @@ func TestRemoveTargetCredentialSources(t *testing.T) {
},
{
name: "Remove 1 of 2 sources",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeCredentialSources: []string{cls[1].GetPublicId()},
resultCredentialSourceIds: []string{cls[0].GetPublicId()},
},
{
name: "Remove 1 duplicate set of 2 sources",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeCredentialSources: []string{
cls[1].GetPublicId(), cls[1].GetPublicId(),
},
@@ -2479,7 +2489,7 @@ func TestRemoveTargetCredentialSources(t *testing.T) {
},
{
name: "Remove all sources from target",
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
removeCredentialSources: []string{
cls[0].GetPublicId(), cls[1].GetPublicId(),
},
+25 -8
View File
@@ -6,10 +6,12 @@ import (
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/gorm/logger"
)
func TestSession_ImmutableFields(t *testing.T) {
@@ -245,16 +247,20 @@ func TestConnectionState_ImmutableFields(t *testing.T) {
_, _ = iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
session := TestDefaultSession(t, conn, wrapper, iamRepo)
connection := TestConnection(t, conn, session.PublicId, "127.0.0.1", 22, "127.0.0.1", 2222)
state := TestConnectionState(t, conn, connection.PublicId, StatusClosed)
state := TestConnectionState(t, conn, connection.PublicId, StatusConnected)
var new ConnectionState
err := rw.LookupWhere(context.Background(), &new, "connection_id = ? and state = ?", state.ConnectionId, state.Status)
require.NoError(t, err)
conn.Logger = logger.Default.LogMode(logger.Info)
tests := []struct {
name string
update *ConnectionState
fieldMask []string
name string
update *ConnectionState
fieldMask []string
wantErrMatch *errors.Template
wantErrContains string
}{
{
name: "session_id",
@@ -272,7 +278,9 @@ func TestConnectionState_ImmutableFields(t *testing.T) {
s.Status = "closed"
return s
}(),
fieldMask: []string{"Status"},
fieldMask: []string{"Status"},
wantErrMatch: errors.T(errors.NotSpecificIntegrity),
wantErrContains: "immutable column",
},
{
name: "start time",
@@ -281,7 +289,9 @@ func TestConnectionState_ImmutableFields(t *testing.T) {
s.StartTime = &ts
return s
}(),
fieldMask: []string{"StartTime"},
fieldMask: []string{"StartTime"},
wantErrMatch: errors.T(errors.InvalidFieldMask),
wantErrContains: "parameter violation",
},
{
name: "previous_end_time",
@@ -290,7 +300,9 @@ func TestConnectionState_ImmutableFields(t *testing.T) {
s.PreviousEndTime = &ts
return s
}(),
fieldMask: []string{"PreviousEndTime"},
fieldMask: []string{"PreviousEndTime"},
wantErrMatch: errors.T(errors.NotSpecificIntegrity),
wantErrContains: "immutable column",
},
}
for _, tt := range tests {
@@ -304,7 +316,12 @@ func TestConnectionState_ImmutableFields(t *testing.T) {
rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true))
require.Error(err)
assert.Equal(0, rowsUpdated)
if tt.wantErrMatch != nil {
assert.Truef(errors.Match(tt.wantErrMatch, err), "wanted error %s and got: %s", tt.wantErrMatch.Code, err.Error())
}
if tt.wantErrContains != "" {
assert.Contains(err.Error(), tt.wantErrContains)
}
after := new.Clone()
err = rw.LookupWhere(context.Background(), after, "connection_id = ? and start_time = ?", new.ConnectionId, new.StartTime)
require.NoError(err)
+13 -8
View File
@@ -1649,21 +1649,26 @@ func testSessionCredentialParams(t *testing.T, conn *db.DB, wrapper wrapping.Wra
rw := db.New(conn)
ctx := context.Background()
stores := vault.TestCredentialStores(t, conn, wrapper, params.ScopeId, 1)
libs := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2)
kms := kms.TestKms(t, conn, wrapper)
targetRepo, err := target.NewRepository(rw, rw, kms)
require.NoError(err)
tcpTarget, _, _, err := targetRepo.LookupTarget(ctx, params.TargetId)
tar, _, _, err := targetRepo.LookupTarget(ctx, params.TargetId)
require.NoError(err)
require.NotNil(tcpTarget)
_, _, _, err = targetRepo.AddTargetCredentialSources(ctx, tcpTarget.GetPublicId(), tcpTarget.GetVersion(), []string{libs[0].PublicId, libs[1].PublicId})
require.NotNil(tar)
stores := vault.TestCredentialStores(t, conn, wrapper, params.ScopeId, 1)
libIds := vault.TestCredentialLibraries(t, conn, wrapper, stores[0].GetPublicId(), 2)
libs := []*target.CredentialLibrary{
target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[0].GetPublicId(), credential.ApplicationPurpose),
target.TestNewCredentialLibrary(tar.GetPublicId(), libIds[1].GetPublicId(), credential.ApplicationPurpose),
}
_, _, _, err = targetRepo.AddTargetCredentialSources(ctx, tar.GetPublicId(), tar.GetVersion(), libs)
require.NoError(err)
creds := []*DynamicCredential{
NewDynamicCredential(libs[0].GetPublicId(), credential.ApplicationPurpose),
NewDynamicCredential(libs[0].GetPublicId(), credential.IngressPurpose),
NewDynamicCredential(libs[1].GetPublicId(), credential.EgressPurpose),
NewDynamicCredential(libIds[0].GetPublicId(), credential.ApplicationPurpose),
NewDynamicCredential(libIds[1].GetPublicId(), credential.ApplicationPurpose),
}
params.DynamicCredentials = creds
return params
+5 -2
View File
@@ -4,7 +4,7 @@ import (
"crypto/ed25519"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/libs/crypto"
wrapping "github.com/hashicorp/go-kms-wrapping"
)
@@ -19,8 +19,11 @@ func DeriveED25519Key(wrapper wrapping.Wrapper, userId, jobId string) (ed25519.P
if jobId != "" {
jId = []byte(jobId)
}
if wrapper == nil {
return nil, nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing wrapper")
}
reader, err := kms.NewDerivedReader(wrapper, 32, uId, jId)
reader, err := crypto.NewDerivedReader(wrapper, 32, uId, jId)
if err != nil {
return nil, nil, errors.WrapDeprecated(err, op)
}
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/libs/crypto"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -39,7 +39,7 @@ func TestDeriveED25519Key(t *testing.T) {
jobId: "jobId",
},
want: func() keys {
reader, err := kms.NewDerivedReader(wrapper, 32, []byte("userId"), []byte("jobId"))
reader, err := crypto.NewDerivedReader(wrapper, 32, []byte("userId"), []byte("jobId"))
require.NoError(t, err)
pub, priv, err := ed25519.GenerateKey(reader)
require.NoError(t, err)
+2 -2
View File
@@ -21,7 +21,7 @@ type CredentialLibrary struct {
// NewCredentialLibrary creates a new in memory CredentialLibrary
// representing the relationship between targetId and credentialLibraryId.
func NewCredentialLibrary(targetId, credentialLibraryId string, _ ...Option) (*CredentialLibrary, error) {
func NewCredentialLibrary(targetId, credentialLibraryId string, purpose credential.Purpose) (*CredentialLibrary, error) {
const op = "target.NewCredentialLibrary"
if targetId == "" {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "no target id")
@@ -34,7 +34,7 @@ func NewCredentialLibrary(targetId, credentialLibraryId string, _ ...Option) (*C
CredentialLibrary: &store.CredentialLibrary{
TargetId: targetId,
CredentialLibraryId: credentialLibraryId,
CredentialPurpose: string(credential.ApplicationPurpose), // application is the only purpose currently supported
CredentialPurpose: string(purpose),
},
}
return t, nil
+1 -1
View File
@@ -55,7 +55,7 @@ func TestCredentialLibrary_New(t *testing.T) {
tt := tt
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := target.NewCredentialLibrary(tt.args.targetId, tt.args.libraryId)
got, err := target.NewCredentialLibrary(tt.args.targetId, tt.args.libraryId, credential.ApplicationPurpose)
if tt.wantErr != 0 {
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
assert.Nil(got)
+5 -5
View File
@@ -30,7 +30,7 @@ type options struct {
WithUserId string
WithType subtypes.Subtype
WithHostSources []string
WithCredentialSources []string
WithCredentialLibraries []*CredentialLibrary
WithSessionMaxSeconds uint32
WithSessionConnectionLimit int32
WithPublicId string
@@ -49,7 +49,7 @@ func getDefaultOptions() options {
WithUserId: "",
WithType: "",
WithHostSources: nil,
WithCredentialSources: nil,
WithCredentialLibraries: nil,
WithSessionMaxSeconds: uint32((8 * time.Hour).Seconds()),
WithSessionConnectionLimit: 1,
WithPublicId: "",
@@ -129,10 +129,10 @@ func WithHostSources(hs []string) Option {
}
}
// WithCredentialSources provides an option for providing a list of credential source ids
func WithCredentialSources(cl []string) Option {
// WithCredentialLibraries provides an option for providing a list of credential libraries.
func WithCredentialLibraries(cl []*CredentialLibrary) Option {
return func(o *options) {
o.WithCredentialSources = cl
o.WithCredentialLibraries = cl
}
}
+31 -3
View File
@@ -3,6 +3,8 @@ package target
import (
"testing"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/target/store"
"github.com/hashicorp/boundary/internal/types/subtypes"
"github.com/stretchr/testify/assert"
)
@@ -106,11 +108,37 @@ func Test_GetOpts(t *testing.T) {
testOpts.WithWorkerFilter = `"/foo" == "bar"`
assert.Equal(opts, testOpts)
})
t.Run("WithCredentialSources", func(t *testing.T) {
t.Run("WithCredentialLibraries", func(t *testing.T) {
assert := assert.New(t)
opts := GetOpts(WithCredentialSources([]string{"alice", "bob"}))
opts := GetOpts(WithCredentialLibraries([]*CredentialLibrary{
{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: "alice",
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: "bob",
CredentialPurpose: string(credential.EgressPurpose),
},
},
}))
testOpts := getDefaultOptions()
testOpts.WithCredentialSources = []string{"alice", "bob"}
testOpts.WithCredentialLibraries = []*CredentialLibrary{
{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: "alice",
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: "bob",
CredentialPurpose: string(credential.EgressPurpose),
},
},
}
assert.Equal(opts, testOpts)
})
}
+2 -1
View File
@@ -13,7 +13,8 @@ current_libraries (library_id) as (
-- returns the current list
select credential_library_id
from target_credential_library
where target_id = @target_id
where target_id = @target_id
and credential_purpose = @purpose
),
keep_libraries (library_id) as (
-- returns the KEEP list
+21 -7
View File
@@ -15,10 +15,15 @@ type AllocFunc func() Target
// be used by the Repository.
type VetFunc func(context.Context, Target) error
// VetCredentialLibrariesFunc is a function that checks the given CredentialLibraries
// to ensure that they are valid for a Target subtype.
type VetCredentialLibrariesFunc func(context.Context, []*CredentialLibrary) error
type registryEntry struct {
alloc AllocFunc
vet VetFunc
prefix string
alloc AllocFunc
vet VetFunc
vetCredentialLibraries VetCredentialLibrariesFunc
prefix string
}
type registry struct {
@@ -71,6 +76,14 @@ func (r *registry) vetFunc(s subtypes.Subtype) (VetFunc, bool) {
return entry.vet, ok
}
func (r *registry) vetCredentialLibrariesFunc(s subtypes.Subtype) (VetCredentialLibrariesFunc, bool) {
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.vetCredentialLibraries, ok
}
func (r *registry) idPrefix(s subtypes.Subtype) (string, bool) {
entry, ok := r.get(s)
if !ok {
@@ -103,10 +116,11 @@ func SubtypeFromId(id string) subtypes.Subtype {
// Register registers repository hooks and the prefixes for a provided Subtype. Register
// panics if the subtype has already been registered or if any of the
// prefixes are associated with another subtype.
func Register(s subtypes.Subtype, af AllocFunc, vf VetFunc, prefix string) {
func Register(s subtypes.Subtype, af AllocFunc, vf VetFunc, vclf VetCredentialLibrariesFunc, prefix string) {
subtypeRegistry.set(s, &registryEntry{
alloc: af,
vet: vf,
prefix: prefix,
alloc: af,
vet: vf,
vetCredentialLibraries: vclf,
prefix: prefix,
})
}
+96 -40
View File
@@ -6,17 +6,46 @@ import (
"fmt"
"strings"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/target/store"
)
// credentialLibrariesPurposeMap is used to group CredentialLibraries by purpose.
type credentialLibrariesPurposeMap map[string][]*CredentialLibrary
func (c credentialLibrariesPurposeMap) add(cl *CredentialLibrary) {
var s []*CredentialLibrary
var ok bool
s, ok = c[cl.CredentialPurpose]
if !ok {
s = make([]*CredentialLibrary, 0, 1)
}
s = append(s, cl)
c[cl.CredentialPurpose] = s
}
func newCredentialLibrariesPurposeMap(cls []*CredentialLibrary) credentialLibrariesPurposeMap {
clpm := make(credentialLibrariesPurposeMap)
for _, p := range credential.ValidPurposes {
clpm[p.String()] = make([]*CredentialLibrary, 0)
}
for _, cl := range cls {
clpm.add(cl)
}
return clpm
}
// AddTargetCredentialSources adds the cIds to the targetId in the repository. The target
// and the list of credential sources attached to the target, after cIds are added,
// will be returned on success.
// The targetVersion must match the current version of the targetId in the repository.
func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, cIds []string, _ ...Option) (Target, []HostSource, []CredentialSource, error) {
func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, cls []*CredentialLibrary, _ ...Option) (Target, []HostSource, []CredentialSource, error) {
const op = "target.(Repository).AddTargetCredentialSources"
if targetId == "" {
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing target id")
@@ -24,16 +53,12 @@ func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId st
if targetVersion == 0 {
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing version")
}
if len(cIds) == 0 {
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing credential source ids")
if len(cls) == 0 {
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing credential libraries")
}
addCredLibs := make([]interface{}, 0, len(cIds))
for _, id := range cIds {
cl, err := NewCredentialLibrary(targetId, id)
if err != nil {
return nil, nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create in memory credential library"))
}
addCredLibs := make([]interface{}, 0, len(cls))
for _, cl := range cls {
addCredLibs = append(addCredLibs, cl)
}
@@ -49,6 +74,14 @@ func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId st
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type))
}
vetCredentialLibraries, ok := subtypeRegistry.vetCredentialLibrariesFunc(t.Subtype())
if !ok {
return nil, nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type))
}
if err := vetCredentialLibraries(ctx, cls); err != nil {
return nil, nil, nil, err
}
target := alloc()
target.SetPublicId(ctx, t.PublicId)
target.SetVersion(targetVersion + 1)
@@ -115,7 +148,7 @@ func (r *Repository) AddTargetCredentialSources(ctx context.Context, targetId st
// DeleteTargetCredentialSources deletes credential sources from a target in the repository.
// The target's current db version must match the targetVersion or an error will be returned.
func (r *Repository) DeleteTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, csIds []string, _ ...Option) (int, error) {
func (r *Repository) DeleteTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, cls []*CredentialLibrary, _ ...Option) (int, error) {
const op = "target.(Repository).DeleteTargetCredentialSources"
if targetId == "" {
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing target id")
@@ -123,16 +156,12 @@ func (r *Repository) DeleteTargetCredentialSources(ctx context.Context, targetId
if targetVersion == 0 {
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing version")
}
if len(csIds) == 0 {
if len(cls) == 0 {
return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing credential source ids")
}
deleteCredLibs := make([]interface{}, 0, len(csIds))
for _, id := range csIds {
cl, err := NewCredentialLibrary(targetId, id)
if err != nil {
return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create in memory credential library"))
}
deleteCredLibs := make([]interface{}, 0, len(cls))
for _, cl := range cls {
deleteCredLibs = append(deleteCredLibs, cl)
}
@@ -208,7 +237,7 @@ func (r *Repository) DeleteTargetCredentialSources(ctx context.Context, targetId
// SetTargetCredentialSources will set the target's credential sources. Set will add
// and/or delete credential sources as need to reconcile the existing credential sources
// with the request. If clIds is empty, all the credential sources will be cleared from the target.
func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, csIds []string, _ ...Option) ([]HostSource, []CredentialSource, int, error) {
func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId string, targetVersion uint32, cls []*CredentialLibrary, _ ...Option) ([]HostSource, []CredentialSource, int, error) {
const op = "target.(Repository).SetTargetCredentialSources"
if targetId == "" {
return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing target id")
@@ -217,10 +246,18 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st
return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing version")
}
changes, err := r.changes(ctx, targetId, csIds)
if err != nil {
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
clpm := newCredentialLibrariesPurposeMap(cls)
var changes []*change
for purpose, cls := range clpm {
c, err := r.changes(ctx, targetId, cls, purpose)
if err != nil {
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
}
changes = append(changes, c...)
}
if len(changes) == 0 {
// Nothing needs to be changed, return early
hostSets, err := fetchHostSources(ctx, r.reader, targetId)
@@ -236,15 +273,11 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st
var deleteCredLibs, addCredLibs []interface{}
for _, c := range changes {
cl, err := NewCredentialLibrary(targetId, c.LibraryId)
if err != nil {
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create in memory target credential library"))
}
switch c.Action {
switch c.action {
case "delete":
deleteCredLibs = append(deleteCredLibs, cl)
deleteCredLibs = append(deleteCredLibs, c.credentialLibrary)
case "add":
addCredLibs = append(addCredLibs, cl)
addCredLibs = append(addCredLibs, c.credentialLibrary)
}
}
@@ -259,6 +292,15 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st
if !ok {
return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type))
}
vetCredentialLibraries, ok := subtypeRegistry.vetCredentialLibrariesFunc(t.Subtype())
if !ok {
return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s is an unsupported target type %s", t.PublicId, t.Type))
}
if err := vetCredentialLibraries(ctx, cls); err != nil {
return nil, nil, db.NoRowsAffected, err
}
target := alloc()
target.SetPublicId(ctx, t.PublicId)
target.SetVersion(targetVersion + 1)
@@ -343,28 +385,33 @@ func (r *Repository) SetTargetCredentialSources(ctx context.Context, targetId st
}
type change struct {
action string
credentialLibrary *CredentialLibrary
}
type changeQueryResult struct {
Action string
LibraryId string
}
func (r *Repository) changes(ctx context.Context, targetId string, clIds []string) ([]*change, error) {
func (r *Repository) changes(ctx context.Context, targetId string, cls []*CredentialLibrary, purpose string) ([]*change, error) {
const op = "target.(Repository).changes"
// TODO ensure that all cls have the same purpose as the given purpose?
var inClauseSpots []string
// starts at 2 because there is already a @1 in the query
for i := 2; i < len(clIds)+2; i++ {
inClauseSpots = append(inClauseSpots, fmt.Sprintf("@%d", i))
var params []interface{}
params = append(params, sql.Named("target_id", targetId), sql.Named("purpose", purpose))
for idx, cl := range cls {
params = append(params, sql.Named(fmt.Sprintf("%d", idx+1), cl.CredentialLibraryId))
inClauseSpots = append(inClauseSpots, fmt.Sprintf("@%d", idx+1))
}
inClause := strings.Join(inClauseSpots, ",")
if inClause == "" {
inClause = "''"
}
query := fmt.Sprintf(setChangesQuery, inClause)
var params []interface{}
params = append(params, sql.Named("target_id", targetId))
for idx, id := range clIds {
params = append(params, sql.Named(fmt.Sprintf("%d", idx+2), id))
}
query := fmt.Sprintf(setChangesQuery, inClause)
rows, err := r.reader.Query(ctx, query, params)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("query failed"))
@@ -373,11 +420,20 @@ func (r *Repository) changes(ctx context.Context, targetId string, clIds []strin
var changes []*change
for rows.Next() {
var chg change
var chg changeQueryResult
if err := r.reader.ScanRows(rows, &chg); err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("scan row failed"))
}
changes = append(changes, &chg)
changes = append(changes, &change{
action: chg.Action,
credentialLibrary: &CredentialLibrary{
CredentialLibrary: &store.CredentialLibrary{
TargetId: targetId,
CredentialLibraryId: chg.LibraryId,
CredentialPurpose: purpose,
},
},
})
}
return changes, nil
}
@@ -0,0 +1,258 @@
package target_test
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/credential/vault"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/targettest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRepository_SetTargetCredentialSources(t *testing.T) {
target.Register(targettest.Subtype, targettest.Alloc, targettest.Vet, targettest.VetCredentialLibraries, targettest.TargetPrefix)
t.Parallel()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
testKms := kms.TestKms(t, conn, wrapper)
repo, err := target.NewRepository(rw, rw, testKms)
require.NoError(t, err)
iamRepo := iam.TestRepo(t, conn, wrapper)
_, proj := iam.TestScopes(t, iamRepo)
cs := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0]
credLibs := vault.TestCredentialLibraries(t, conn, wrapper, cs.GetPublicId(), 2)
lib1 := credLibs[0]
lib2 := credLibs[1]
setupFn := func(tar target.Target) ([]target.CredentialSource, []*target.CredentialLibrary) {
credLibs := vault.TestCredentialLibraries(t, conn, wrapper, cs.GetPublicId(), 10)
cls := make([]*target.CredentialLibrary, 0, len(credLibs))
for _, cl := range credLibs {
cls = append(cls, target.TestNewCredentialLibrary(tar.GetPublicId(), cl.PublicId, credential.ApplicationPurpose))
}
_, _, created, err := repo.AddTargetCredentialSources(context.Background(), tar.GetPublicId(), 1, cls)
require.NoError(t, err)
require.Equal(t, 10, len(created))
return created, cls
}
type args struct {
targetVersion uint32
cls []*target.CredentialLibrary
addToOrigLibs bool
}
tests := []struct {
name string
setup func(target.Target) ([]target.CredentialSource, []*target.CredentialLibrary)
args args
wantAffectedRows int
wantErr bool
wantErrCode errors.Code
}{
{
name: "clear",
setup: setupFn,
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{},
},
wantErr: false,
wantAffectedRows: 10,
},
{
name: "no-change",
setup: setupFn,
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{},
addToOrigLibs: true,
},
wantErr: false,
wantAffectedRows: 0,
},
{
name: "add-cred-sources",
setup: setupFn,
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: false,
wantAffectedRows: 2,
},
{
name: "add-multiple-purposes",
setup: setupFn,
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: false,
wantAffectedRows: 3,
},
{
name: "remove-add-change-purpose",
setup: func(tar target.Target) ([]target.CredentialSource, []*target.CredentialLibrary) {
cls := []*target.CredentialLibrary{
target.TestNewCredentialLibrary(tar.GetPublicId(), lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary(tar.GetPublicId(), lib2.PublicId, credential.ApplicationPurpose),
}
_, _, created, err := repo.AddTargetCredentialSources(context.Background(), tar.GetPublicId(), 1, cls)
require.NoError(t, err)
require.Equal(t, 2, len(created))
return created, cls
},
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.EgressPurpose),
},
addToOrigLibs: false,
},
wantErr: false,
wantAffectedRows: 4,
},
{
name: "zero version",
setup: setupFn,
args: args{
targetVersion: 0,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "bad version",
setup: setupFn,
args: args{
targetVersion: 1000,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: true,
wantErrCode: errors.VersionMismatch,
},
{
name: "remove existing and add cred libs",
setup: setupFn,
args: args{
targetVersion: 2,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: false,
},
wantErr: false,
wantAffectedRows: 12,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
tar := targettest.TestNewTestTarget(t, conn, proj.PublicId, tt.name)
var origCredSources []target.CredentialSource
var origCredLibraries []*target.CredentialLibrary
if tt.setup != nil {
origCredSources, origCredLibraries = tt.setup(tar)
}
wantCredSources := make(map[string]target.CredentialSource)
for _, cl := range tt.args.cls {
cl.TargetId = tar.GetPublicId()
wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{
CredentialLibrary: cl.CredentialLibrary,
}
}
if tt.args.addToOrigLibs {
tt.args.cls = append(tt.args.cls, origCredLibraries...)
for _, cl := range origCredLibraries {
wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{
CredentialLibrary: cl.CredentialLibrary,
}
}
}
origTarget, _, lookupCredSources, err := repo.LookupTarget(context.Background(), tar.GetPublicId())
require.NoError(err)
assert.Equal(origCredSources, lookupCredSources)
_, got, affectedRows, err := repo.SetTargetCredentialSources(context.Background(), tar.GetPublicId(), tt.args.targetVersion, tt.args.cls)
if tt.wantErr {
require.Error(err)
assert.Equal(0, affectedRows)
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err.Error())
return
}
t.Log(err)
require.NoError(err)
assert.Equal(tt.wantAffectedRows, affectedRows)
assert.Equal(len(wantCredSources), len(got))
for _, cs := range got {
w, ok := wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())]
assert.True(ok, "got unexpected credentialsource %v", cs)
assert.Equal(w.Id(), cs.Id())
assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose())
}
foundTarget, _, _, err := repo.LookupTarget(context.Background(), tar.GetPublicId())
require.NoError(err)
if tt.name != "no-change" {
assert.Equalf(tt.args.targetVersion+1, foundTarget.GetVersion(), "%s unexpected version: %d/%d", tt.name, tt.args.targetVersion+1, foundTarget.GetVersion())
assert.Equalf(origTarget.GetVersion(), foundTarget.GetVersion()-1, "%s unexpected version: %d/%d", tt.name, origTarget.GetVersion(), foundTarget.GetVersion()-1)
}
})
}
t.Run("missing-target-id", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
cl1 := target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "", 1, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.InvalidParameter), err), "unexpected error %s", err.Error())
})
t.Run("target-not-found", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
cl1 := target.TestNewCredentialLibrary("fake-target-id", lib1.PublicId, credential.ApplicationPurpose)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "fake-target-id", 1, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "unexpected error %s", err.Error())
})
}
@@ -0,0 +1,307 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// source: controller/storage/target/targettest/store/v1/target.proto
package store
import (
timestamp "github.com/hashicorp/boundary/internal/db/timestamp"
_ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions"
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 Target struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// public_id is used to access the targettest.Target via an API
// @inject_tag: gorm:"primary_key"
PublicId string `protobuf:"bytes,10,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
// scope id for the targettest.Target
// @inject_tag: `gorm:"default:null"`
ScopeId string `protobuf:"bytes,20,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" gorm:"default:null"`
// name is the optional friendly name used to
// access the targettest.Target via an API
// @inject_tag: `gorm:"default:null"`
Name string `protobuf:"bytes,30,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
// description of the targettest.Target
// @inject_tag: `gorm:"default:null"`
Description string `protobuf:"bytes,40,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
// create_time from the RDBMS
// @inject_tag: `gorm:"default:current_timestamp"`
CreateTime *timestamp.Timestamp `protobuf:"bytes,50,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
// update_time from the RDBMS
// @inject_tag: `gorm:"default:current_timestamp"`
UpdateTime *timestamp.Timestamp `protobuf:"bytes,60,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
// version allows optimistic locking of the targettest.Target when modifying the
// targettest.Target
// @inject_tag: `gorm:"default:null"`
Version uint32 `protobuf:"varint,70,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
// default port of the targettest.Target
// @inject_tag: `gorm:"default:null"`
DefaultPort uint32 `protobuf:"varint,80,opt,name=default_port,json=defaultPort,proto3" json:"default_port,omitempty" gorm:"default:null"`
// Maximum total lifetime of a created session, in seconds
// @inject_tag: `gorm:"default:null"`
SessionMaxSeconds uint32 `protobuf:"varint,100,opt,name=session_max_seconds,json=sessionMaxSeconds,proto3" json:"session_max_seconds,omitempty" gorm:"default:null"`
// Maximum number of connections in a session
// @inject_tag: `gorm:"default:null"`
SessionConnectionLimit int32 `protobuf:"varint,110,opt,name=session_connection_limit,json=sessionConnectionLimit,proto3" json:"session_connection_limit,omitempty" gorm:"default:null"`
// A boolean expression that allows filtering the workers that can handle a session
// @inject_tag: `gorm:"default:null"`
WorkerFilter string `protobuf:"bytes,120,opt,name=worker_filter,json=workerFilter,proto3" json:"worker_filter,omitempty" gorm:"default:null"`
}
func (x *Target) Reset() {
*x = Target{}
if protoimpl.UnsafeEnabled {
mi := &file_controller_storage_target_targettest_store_v1_target_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Target) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Target) ProtoMessage() {}
func (x *Target) ProtoReflect() protoreflect.Message {
mi := &file_controller_storage_target_targettest_store_v1_target_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 Target.ProtoReflect.Descriptor instead.
func (*Target) Descriptor() ([]byte, []int) {
return file_controller_storage_target_targettest_store_v1_target_proto_rawDescGZIP(), []int{0}
}
func (x *Target) GetPublicId() string {
if x != nil {
return x.PublicId
}
return ""
}
func (x *Target) GetScopeId() string {
if x != nil {
return x.ScopeId
}
return ""
}
func (x *Target) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Target) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Target) GetCreateTime() *timestamp.Timestamp {
if x != nil {
return x.CreateTime
}
return nil
}
func (x *Target) GetUpdateTime() *timestamp.Timestamp {
if x != nil {
return x.UpdateTime
}
return nil
}
func (x *Target) GetVersion() uint32 {
if x != nil {
return x.Version
}
return 0
}
func (x *Target) GetDefaultPort() uint32 {
if x != nil {
return x.DefaultPort
}
return 0
}
func (x *Target) GetSessionMaxSeconds() uint32 {
if x != nil {
return x.SessionMaxSeconds
}
return 0
}
func (x *Target) GetSessionConnectionLimit() int32 {
if x != nil {
return x.SessionConnectionLimit
}
return 0
}
func (x *Target) GetWorkerFilter() string {
if x != nil {
return x.WorkerFilter
}
return ""
}
var File_controller_storage_target_targettest_store_v1_target_proto protoreflect.FileDescriptor
var file_controller_storage_target_targettest_store_v1_target_proto_rawDesc = []byte{
0x0a, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2f, 0x74, 0x61, 0x72, 0x67,
0x65, 0x74, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2d, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x74, 0x65,
0x73, 0x74, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f,
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x05, 0x0a, 0x06, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64,
0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64,
0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x40, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69,
0x6d, 0x65, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65,
0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x2a, 0xc2,
0xdd, 0x29, 0x26, 0x0a, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74,
0x12, 0x17, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x66,
0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75,
0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5c, 0x0a, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x64, 0x20,
0x01, 0x28, 0x0d, 0x42, 0x2c, 0xc2, 0xdd, 0x29, 0x28, 0x0a, 0x11, 0x53, 0x65, 0x73, 0x73, 0x69,
0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x13, 0x73, 0x65,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
0x73, 0x52, 0x11, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x63,
0x6f, 0x6e, 0x64, 0x73, 0x12, 0x70, 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74,
0x18, 0x6e, 0x20, 0x01, 0x28, 0x05, 0x42, 0x36, 0xc2, 0xdd, 0x29, 0x32, 0x0a, 0x16, 0x53, 0x65,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c,
0x69, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x16,
0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x46, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72,
0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x78, 0x20, 0x01, 0x28, 0x09, 0x42, 0x21, 0xc2,
0xdd, 0x29, 0x1d, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65,
0x72, 0x12, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x46,
0x5a, 0x44, 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2f,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_controller_storage_target_targettest_store_v1_target_proto_rawDescOnce sync.Once
file_controller_storage_target_targettest_store_v1_target_proto_rawDescData = file_controller_storage_target_targettest_store_v1_target_proto_rawDesc
)
func file_controller_storage_target_targettest_store_v1_target_proto_rawDescGZIP() []byte {
file_controller_storage_target_targettest_store_v1_target_proto_rawDescOnce.Do(func() {
file_controller_storage_target_targettest_store_v1_target_proto_rawDescData = protoimpl.X.CompressGZIP(file_controller_storage_target_targettest_store_v1_target_proto_rawDescData)
})
return file_controller_storage_target_targettest_store_v1_target_proto_rawDescData
}
var file_controller_storage_target_targettest_store_v1_target_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_controller_storage_target_targettest_store_v1_target_proto_goTypes = []interface{}{
(*Target)(nil), // 0: controller.storage.target.targettest.store.v1.Target
(*timestamp.Timestamp)(nil), // 1: controller.storage.timestamp.v1.Timestamp
}
var file_controller_storage_target_targettest_store_v1_target_proto_depIdxs = []int32{
1, // 0: controller.storage.target.targettest.store.v1.Target.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
1, // 1: controller.storage.target.targettest.store.v1.Target.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_controller_storage_target_targettest_store_v1_target_proto_init() }
func file_controller_storage_target_targettest_store_v1_target_proto_init() {
if File_controller_storage_target_targettest_store_v1_target_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_controller_storage_target_targettest_store_v1_target_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Target); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_controller_storage_target_targettest_store_v1_target_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_controller_storage_target_targettest_store_v1_target_proto_goTypes,
DependencyIndexes: file_controller_storage_target_targettest_store_v1_target_proto_depIdxs,
MessageInfos: file_controller_storage_target_targettest_store_v1_target_proto_msgTypes,
}.Build()
File_controller_storage_target_targettest_store_v1_target_proto = out.File
file_controller_storage_target_targettest_store_v1_target_proto_rawDesc = nil
file_controller_storage_target_targettest_store_v1_target_proto_goTypes = nil
file_controller_storage_target_targettest_store_v1_target_proto_depIdxs = nil
}
+267
View File
@@ -0,0 +1,267 @@
// Package targettest provides a test target subtype for use by the target
// package. Note that it leverages the tcp.Target's database table to avoid
// needing schema migrations just for tests.
package targettest
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/timestamp"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/targettest/store"
"github.com/hashicorp/boundary/internal/types/subtypes"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
)
const (
Subtype = subtypes.Subtype("tcp")
TargetPrefix = "ttcp"
)
// Target is a target.Target used for tests.
type Target struct {
*store.Target
tableName string `gorm:"-"`
}
var (
_ target.Target = (*Target)(nil)
_ db.VetForWriter = (*Target)(nil)
_ oplog.ReplayableMessage = (*Target)(nil)
)
// VetForWrite implements db.VetForWrite() interface and validates the tcp target
// before it's written.
func (t *Target) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error {
const op = "target_test.(Target).VetForWrite"
if t.PublicId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing public id")
}
if opType == db.CreateOp {
if t.ScopeId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing scope id")
}
if t.Name == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing name")
}
}
return nil
}
// TableName returns the tablename to override the default gorm table name
func (t *Target) TableName() string {
if t.tableName != "" {
return t.tableName
}
return "target_tcp"
}
// SetTableName sets the tablename and satisfies the ReplayableMessage
// interface. If the caller attempts to set the name to "" the name will be
// reset to the default name.
func (t *Target) SetTableName(n string) {
t.tableName = n
}
func (t *Target) GetPublicId() string {
return t.PublicId
}
func (t *Target) GetScopeId() string {
return t.ScopeId
}
func (t *Target) GetDefaultPort() uint32 {
return t.DefaultPort
}
func (t *Target) GetName() string {
return t.Name
}
func (t *Target) GetDescription() string {
return t.Description
}
func (t *Target) GetVersion() uint32 {
return t.Version
}
func (t *Target) GetType() subtypes.Subtype {
return Subtype
}
func (t *Target) GetCreateTime() *timestamp.Timestamp {
return t.CreateTime
}
func (t *Target) GetUpdateTime() *timestamp.Timestamp {
return t.UpdateTime
}
func (t *Target) GetSessionMaxSeconds() uint32 {
return t.SessionMaxSeconds
}
func (t *Target) GetSessionConnectionLimit() int32 {
return t.SessionConnectionLimit
}
func (t *Target) GetWorkerFilter() string {
return t.WorkerFilter
}
func (t *Target) Clone() target.Target {
cp := proto.Clone(t.Target)
return &Target{
Target: cp.(*store.Target),
}
}
func (t *Target) SetPublicId(_ context.Context, publicId string) error {
t.PublicId = publicId
return nil
}
func (t *Target) SetScopeId(scopeId string) {
t.ScopeId = scopeId
}
func (t *Target) SetName(name string) {
t.Name = name
}
func (t *Target) SetDescription(description string) {
t.Description = description
}
func (t *Target) SetVersion(v uint32) {
t.Version = v
}
func (t *Target) SetDefaultPort(port uint32) {
t.DefaultPort = port
}
func (t *Target) SetCreateTime(ts *timestamp.Timestamp) {
t.CreateTime = ts
}
func (t *Target) SetUpdateTime(ts *timestamp.Timestamp) {
t.UpdateTime = ts
}
func (t *Target) SetSessionMaxSeconds(s uint32) {
t.SessionMaxSeconds = s
}
func (t *Target) SetSessionConnectionLimit(l int32) {
t.SessionConnectionLimit = l
}
func (t *Target) SetWorkerFilter(f string) {
t.WorkerFilter = f
}
func (t *Target) Oplog(op oplog.OpType) oplog.Metadata {
return oplog.Metadata{
"resource-public-id": []string{t.PublicId},
"resource-type": []string{"tcp target"},
"op-type": []string{op.String()},
"scope-id": []string{t.ScopeId},
}
}
// Alloc creates an in-memory Target.
func Alloc() target.Target {
return &Target{
Target: &store.Target{},
}
}
// Vet checks that the given Target is a targettest.Target and that it is not nil.
func Vet(ctx context.Context, t target.Target) error {
const op = "targettest.Vet"
tt, ok := t.(*Target)
if !ok {
return errors.New(ctx, errors.InvalidParameter, op, "target is not a tcp.Target")
}
if tt == nil {
return errors.New(ctx, errors.InvalidParameter, op, "missing target")
}
if tt.Target == nil {
return errors.New(ctx, errors.InvalidParameter, op, "missing target store")
}
return nil
}
// VetCredentialLibraries allows for any CredentialLibraries.
func VetCredentialLibraries(_ context.Context, _ []*target.CredentialLibrary) error {
return nil
}
// New creates a targettest.Target.
func New(scopeId string, opt ...target.Option) (*Target, error) {
const op = "target_test.New"
opts := target.GetOpts(opt...)
if scopeId == "" {
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing scope id")
}
t := &Target{
Target: &store.Target{
ScopeId: scopeId,
Name: opts.WithName,
Description: opts.WithDescription,
DefaultPort: opts.WithDefaultPort,
SessionConnectionLimit: opts.WithSessionConnectionLimit,
SessionMaxSeconds: opts.WithSessionMaxSeconds,
WorkerFilter: opts.WithWorkerFilter,
},
}
return t, nil
}
// TestNewTestTarget is a test helper for creating a targettest.Target.
func TestNewTestTarget(t *testing.T, conn *db.DB, scopeId, name string, opt ...target.Option) *Target {
t.Helper()
opt = append(opt, target.WithName(name))
opts := target.GetOpts(opt...)
require := require.New(t)
rw := db.New(conn)
tar, err := New(scopeId, opt...)
require.NoError(err)
id, err := db.NewPublicId(TargetPrefix)
require.NoError(err)
tar.PublicId = id
err = rw.Create(context.Background(), tar)
require.NoError(err)
if len(opts.WithHostSources) > 0 {
newHostSets := make([]interface{}, 0, len(opts.WithHostSources))
for _, s := range opts.WithHostSources {
hostSet, err := target.NewTargetHostSet(tar.PublicId, s)
require.NoError(err)
newHostSets = append(newHostSets, hostSet)
}
err := rw.CreateItems(context.Background(), newHostSets)
require.NoError(err)
}
if len(opts.WithCredentialLibraries) > 0 {
newCredLibs := make([]interface{}, 0, len(opts.WithCredentialLibraries))
for _, cl := range opts.WithCredentialLibraries {
cl.TargetId = tar.PublicId
newCredLibs = append(newCredLibs, cl)
}
err := rw.CreateItems(context.Background(), newCredLibs)
require.NoError(err)
}
return tar
}
+16 -1
View File
@@ -2,13 +2,15 @@ package tcp
import (
"context"
"fmt"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/target"
)
func init() {
target.Register(Subtype, allocTarget, vet, TargetPrefix)
target.Register(Subtype, allocTarget, vet, vetCredentialLibraries, TargetPrefix)
}
const (
@@ -35,3 +37,16 @@ func vet(ctx context.Context, t target.Target) error {
}
return nil
}
// vetCredentialLibraries checks that all of the provided credential libriaries have a CredentialPurpose
// of ApplicationPurpose. Any other CredentialPurpose will result in an error.
func vetCredentialLibraries(ctx context.Context, cls []*target.CredentialLibrary) error {
const op = "tcp.vetCredentialLibraries"
for _, cl := range cls {
if cl.CredentialPurpose != string(credential.ApplicationPurpose) {
return errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("tcp.Target only supports credential purpose: %q", credential.ApplicationPurpose))
}
}
return nil
}
@@ -2,10 +2,10 @@ package tcp_test
import (
"context"
"sort"
"testing"
"time"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/credential/vault"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/errors"
@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/store"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -39,14 +40,14 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
type args struct {
targetVersion uint32
credLibIds []string
cls []*target.CredentialLibrary
}
tests := []struct {
name string
args args
wantCredLibIds []string
wantErr bool
wantErrCode errors.Code
name string
args args
wantCredSources map[string]target.CredentialSource
wantErr bool
wantErrCode errors.Code
}{
{
name: "zero-version",
@@ -68,34 +69,95 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
name: "valid-single-source",
args: args{
targetVersion: 1,
credLibIds: []string{lib1.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
},
},
wantCredLibIds: []string{lib1.PublicId},
wantErr: false,
wantCredSources: map[string]target.CredentialSource{
lib1.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: lib1.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
},
wantErr: false,
},
{
name: "valid-multiple-sources",
args: args{
targetVersion: 1,
credLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib3.PublicId, credential.ApplicationPurpose),
},
},
wantCredLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId},
wantErr: false,
wantCredSources: map[string]target.CredentialSource{
lib1.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: lib1.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
lib2.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: lib2.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
lib3.PublicId + "_" + string(credential.ApplicationPurpose): &target.TargetLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: lib3.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
},
},
wantErr: false,
},
{
name: "invalid-source-id",
args: args{
targetVersion: 1,
credLibIds: []string{lib1.PublicId, lib2.PublicId, lib3.PublicId, "invalid-source-id"},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib3.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", "invalid-source-id", credential.ApplicationPurpose),
},
},
wantErr: true,
wantErrCode: errors.NotSpecificIntegrity,
},
{
name: "egress-credential-purpose",
args: args{
targetVersion: 1,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose),
},
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "ingress-credential-purpose",
args: args{
targetVersion: 1,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.IngressPurpose),
},
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "bad-version",
args: args{
targetVersion: 1000,
credLibIds: []string{lib1.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
},
},
wantErr: true,
wantErrCode: errors.VersionMismatch,
@@ -106,20 +168,25 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
assert, require := assert.New(t), require.New(t)
projTarget := tcp.TestTarget(t, conn, staticProj.PublicId, tt.name)
gotTarget, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, tt.args.targetVersion, tt.args.credLibIds)
for _, cl := range tt.args.cls {
cl.TargetId = projTarget.PublicId
}
gotTarget, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, tt.args.targetVersion, tt.args.cls)
if tt.wantErr {
require.Error(err)
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err.Error())
return
}
require.NoError(err)
assert.Len(gotCredSources, len(tt.wantCredLibIds))
gotCredSourcesMap := map[string]target.CredentialSource{}
for _, s := range gotCredSources {
gotCredSourcesMap[s.Id()] = s
}
for _, id := range tt.wantCredLibIds {
assert.NotEmpty(gotCredSourcesMap[id])
assert.Len(gotCredSources, len(tt.wantCredSources))
for _, cs := range gotCredSources {
w, ok := tt.wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())]
assert.True(ok, "got unexpected credentialsource %v", cs)
assert.Equal(w.Id(), cs.Id())
assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose())
}
// test to see of the target version update oplog was created
@@ -132,9 +199,13 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
assert.Equal(projTarget.GetVersion(), tar.GetVersion()-1)
assert.True(proto.Equal(gotTarget.(*tcp.Target), tar.(*tcp.Target)))
assert.Equal(gotCredSources, lookupCredSources)
for _, s := range lookupCredSources {
assert.NotEmpty(gotCredSourcesMap[s.Id()])
assert.Equal(projTarget.PublicId, s.TargetId())
for _, cs := range lookupCredSources {
w, ok := tt.wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())]
assert.True(ok, "got unexpected credentialsource %v", cs)
assert.Equal(w.Id(), cs.Id())
assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose())
assert.Equal(projTarget.PublicId, cs.TargetId())
}
})
}
@@ -142,18 +213,22 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
assert, require := assert.New(t), require.New(t)
projTarget := tcp.TestTarget(t, conn, staticProj.PublicId, "add-existing")
_, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 1, []string{lib1.PublicId})
cl1 := target.TestNewCredentialLibrary(projTarget.PublicId, lib1.PublicId, credential.ApplicationPurpose)
cl2 := target.TestNewCredentialLibrary(projTarget.PublicId, lib2.PublicId, credential.ApplicationPurpose)
cl3 := target.TestNewCredentialLibrary(projTarget.PublicId, lib3.PublicId, credential.ApplicationPurpose)
_, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 1, []*target.CredentialLibrary{cl1})
require.NoError(err)
assert.Len(gotCredSources, 1)
assert.Equal(lib1.PublicId, gotCredSources[0].Id())
// Adding lib1 again should error
_, _, _, err = repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []string{lib1.PublicId})
_, _, _, err = repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.True(errors.Match(errors.T(errors.NotUnique), err))
// Adding multiple with lib1 in set should error
_, _, _, err = repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []string{lib3.PublicId, lib2.PublicId, lib1.PublicId})
_, _, _, err = repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []*target.CredentialLibrary{cl3, cl2, cl1})
require.Error(err)
assert.True(errors.Match(errors.T(errors.NotUnique), err))
@@ -166,7 +241,8 @@ func TestRepository_AddTargetCredentialSources(t *testing.T) {
t.Run("target-not-found", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
_, _, _, err := repo.AddTargetCredentialSources(context.Background(), "fake-target-id", 1, []string{lib1.PublicId})
cl1 := target.TestNewCredentialLibrary("fake-target-id", lib1.PublicId, credential.ApplicationPurpose)
_, _, _, err := repo.AddTargetCredentialSources(context.Background(), "fake-target-id", 1, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "unexpected error %s", err.Error())
@@ -275,29 +351,29 @@ func TestRepository_DeleteTargetCredentialSources(t *testing.T) {
assert, require := assert.New(t), require.New(t)
cs := css[i]
target := tcp.TestTarget(t, conn, proj.PublicId, tt.name)
tar := tcp.TestTarget(t, conn, proj.PublicId, tt.name)
clIds := make([]string, 0, tt.args.createCnt)
cls := make([]*target.CredentialLibrary, 0, tt.args.createCnt)
if tt.args.createCnt > 0 {
credLibs := vault.TestCredentialLibraries(t, conn, wrapper, cs.PublicId, tt.args.createCnt)
for _, cl := range credLibs {
clIds = append(clIds, cl.PublicId)
cls = append(cls, target.TestNewCredentialLibrary(tar.GetPublicId(), cl.PublicId, credential.ApplicationPurpose))
}
}
_, _, addedCredSources, err := repo.AddTargetCredentialSources(context.Background(), target.GetPublicId(), 1, clIds)
_, _, addedCredSources, err := repo.AddTargetCredentialSources(context.Background(), tar.GetPublicId(), 1, cls)
require.NoError(err)
assert.Equal(tt.args.createCnt, len(addedCredSources))
deleteCredSources := make([]string, 0, tt.args.deleteCnt)
deleteCredSources := make([]*target.CredentialLibrary, 0, tt.args.deleteCnt)
for i := 0; i < tt.args.deleteCnt; i++ {
deleteCredSources = append(deleteCredSources, clIds[i])
deleteCredSources = append(deleteCredSources, cls[i])
}
var targetId string
switch {
case tt.args.targetIdOverride != nil:
targetId = *tt.args.targetIdOverride
default:
targetId = target.GetPublicId()
targetId = tar.GetPublicId()
}
var targetVersion uint32
switch {
@@ -317,7 +393,7 @@ func TestRepository_DeleteTargetCredentialSources(t *testing.T) {
assert.Equal(tt.wantRowsDeleted, deletedRows)
// we should find the oplog for the delete of target credential libraries
err = db.TestVerifyOplog(t, rw, target.GetPublicId(), db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second))
err = db.TestVerifyOplog(t, rw, tar.GetPublicId(), db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second))
assert.NoError(err)
})
}
@@ -333,18 +409,22 @@ func TestRepository_DeleteTargetCredentialSources(t *testing.T) {
lib3 := libs[2]
projTarget := tcp.TestTarget(t, conn, proj.PublicId, "add-existing")
_, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 1, []string{lib1.PublicId, lib2.PublicId})
cl1 := target.TestNewCredentialLibrary(projTarget.PublicId, lib1.PublicId, credential.ApplicationPurpose)
cl2 := target.TestNewCredentialLibrary(projTarget.PublicId, lib2.PublicId, credential.ApplicationPurpose)
cl3 := target.TestNewCredentialLibrary(projTarget.PublicId, lib3.PublicId, credential.ApplicationPurpose)
_, _, gotCredSources, err := repo.AddTargetCredentialSources(context.Background(), projTarget.PublicId, 1, []*target.CredentialLibrary{cl1, cl2})
require.NoError(err)
assert.Len(gotCredSources, 2)
// Deleting an unassociated source should return an error
delCount, err := repo.DeleteTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []string{lib3.PublicId})
delCount, err := repo.DeleteTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []*target.CredentialLibrary{cl3})
require.Error(err)
assert.True(errors.Match(errors.T(errors.MultipleRecords), err))
assert.Equal(0, delCount)
// Deleting sources which includes an unassociated source should return an error
delCount, err = repo.DeleteTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []string{lib1.PublicId, lib2.PublicId, lib3.PublicId})
delCount, err = repo.DeleteTargetCredentialSources(context.Background(), projTarget.PublicId, 2, []*target.CredentialLibrary{cl1, cl2, cl3})
require.Error(err)
assert.True(errors.Match(errors.T(errors.MultipleRecords), err))
assert.Equal(0, delCount)
@@ -373,26 +453,26 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
lib1 := credLibs[0]
lib2 := credLibs[1]
setupFn := func(target target.Target) []target.CredentialSource {
setupFn := func(tar target.Target) ([]target.CredentialSource, []*target.CredentialLibrary) {
credLibs := vault.TestCredentialLibraries(t, conn, wrapper, cs.GetPublicId(), 10)
clIds := make([]string, 0, len(credLibs))
cls := make([]*target.CredentialLibrary, 0, len(credLibs))
for _, cl := range credLibs {
clIds = append(clIds, cl.PublicId)
cls = append(cls, target.TestNewCredentialLibrary(tar.GetPublicId(), cl.PublicId, credential.ApplicationPurpose))
}
_, _, created, err := repo.AddTargetCredentialSources(context.Background(), target.GetPublicId(), 1, clIds)
_, _, created, err := repo.AddTargetCredentialSources(context.Background(), tar.GetPublicId(), 1, cls)
require.NoError(t, err)
require.Equal(t, 10, len(created))
return created
return created, cls
}
type args struct {
targetVersion uint32
clIds []string
cls []*target.CredentialLibrary
addToOrigLibs bool
}
tests := []struct {
name string
setup func(target.Target) []target.CredentialSource
setup func(target.Target) ([]target.CredentialSource, []*target.CredentialLibrary)
args args
wantAffectedRows int
wantErr bool
@@ -403,7 +483,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 2,
clIds: []string{},
cls: []*target.CredentialLibrary{},
},
wantErr: false,
wantAffectedRows: 10,
@@ -413,7 +493,7 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 2,
clIds: []string{},
cls: []*target.CredentialLibrary{},
addToOrigLibs: true,
},
wantErr: false,
@@ -424,7 +504,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 2,
clIds: []string{lib1.PublicId, lib2.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: false,
@@ -435,7 +518,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 0,
clIds: []string{lib1.PublicId, lib2.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: true,
@@ -446,7 +532,10 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 1000,
clIds: []string{lib1.PublicId, lib2.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: true,
},
wantErr: true,
@@ -457,12 +546,39 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
setup: setupFn,
args: args{
targetVersion: 2,
clIds: []string{lib1.PublicId, lib2.PublicId},
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose),
target.TestNewCredentialLibrary("", lib2.PublicId, credential.ApplicationPurpose),
},
addToOrigLibs: false,
},
wantErr: false,
wantAffectedRows: 12,
},
{
name: "egress-credential-purpose",
setup: setupFn,
args: args{
targetVersion: 1,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.EgressPurpose),
},
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "ingress-credential-purpose",
setup: setupFn,
args: args{
targetVersion: 1,
cls: []*target.CredentialLibrary{
target.TestNewCredentialLibrary("", lib1.PublicId, credential.IngressPurpose),
},
},
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -471,22 +587,32 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
tar := tcp.TestTarget(t, conn, proj.PublicId, tt.name)
var origCredSources []target.CredentialSource
var origCredLibraries []*target.CredentialLibrary
if tt.setup != nil {
origCredSources = tt.setup(tar)
origCredSources, origCredLibraries = tt.setup(tar)
}
wantCredSources := make(map[string]target.CredentialSource)
for _, cl := range tt.args.cls {
cl.TargetId = tar.GetPublicId()
wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{
CredentialLibrary: cl.CredentialLibrary,
}
}
if tt.args.addToOrigLibs {
origIds := make([]string, 0, len(origCredSources))
for _, cl := range origCredSources {
origIds = append(origIds, cl.Id())
tt.args.cls = append(tt.args.cls, origCredLibraries...)
for _, cl := range origCredLibraries {
wantCredSources[cl.CredentialLibraryId+"_"+cl.CredentialPurpose] = &target.TargetLibrary{
CredentialLibrary: cl.CredentialLibrary,
}
}
tt.args.clIds = append(tt.args.clIds, origIds...)
}
origTarget, _, lookupCredSources, err := repo.LookupTarget(context.Background(), tar.GetPublicId())
require.NoError(err)
assert.Equal(origCredSources, lookupCredSources)
_, got, affectedRows, err := repo.SetTargetCredentialSources(context.Background(), tar.GetPublicId(), tt.args.targetVersion, tt.args.clIds)
_, got, affectedRows, err := repo.SetTargetCredentialSources(context.Background(), tar.GetPublicId(), tt.args.targetVersion, tt.args.cls)
if tt.wantErr {
require.Error(err)
assert.Equal(0, affectedRows)
@@ -496,21 +622,15 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
t.Log(err)
require.NoError(err)
assert.Equal(tt.wantAffectedRows, affectedRows)
assert.Equal(len(tt.args.clIds), len(got))
var wantIds []string
wantIds = append(wantIds, tt.args.clIds...)
sort.Strings(wantIds)
assert.Equal(len(wantCredSources), len(got))
var gotIds []string
if len(got) > 0 {
gotIds = make([]string, 0, len(got))
for _, s := range got {
gotIds = append(gotIds, s.Id())
}
for _, cs := range got {
w, ok := wantCredSources[cs.Id()+"_"+string(cs.CredentialPurpose())]
assert.True(ok, "got unexpected credentialsource %v", cs)
assert.Equal(w.Id(), cs.Id())
assert.Equal(w.CredentialPurpose(), cs.CredentialPurpose())
}
sort.Strings(gotIds)
assert.Equal(wantIds, gotIds)
foundTarget, _, _, err := repo.LookupTarget(context.Background(), tar.GetPublicId())
require.NoError(err)
@@ -523,7 +643,8 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
t.Run("missing-target-id", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "", 1, []string{lib1.PublicId})
cl1 := target.TestNewCredentialLibrary("", lib1.PublicId, credential.ApplicationPurpose)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "", 1, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.InvalidParameter), err), "unexpected error %s", err.Error())
@@ -531,7 +652,8 @@ func TestRepository_SetTargetCredentialSources(t *testing.T) {
t.Run("target-not-found", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "fake-target-id", 1, []string{lib1.PublicId})
cl1 := target.TestNewCredentialLibrary("fake-target-id", lib1.PublicId, credential.ApplicationPurpose)
_, _, _, err := repo.SetTargetCredentialSources(context.Background(), "fake-target-id", 1, []*target.CredentialLibrary{cl1})
require.Error(err)
assert.Truef(errors.Match(errors.T(errors.RecordNotFound), err), "unexpected error %s", err.Error())
@@ -5,6 +5,7 @@ import (
"testing"
"time"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/credential/vault"
"github.com/hashicorp/boundary/internal/db"
dbassert "github.com/hashicorp/boundary/internal/db/assert"
@@ -14,6 +15,7 @@ import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/store"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -39,9 +41,16 @@ func TestRepository_CreateTarget(t *testing.T) {
cs := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0]
credSources := vault.TestCredentialLibraries(t, conn, wrapper, cs.GetPublicId(), 2)
var clIds []string
var credLibraries []*target.CredentialLibrary
var credLibIds []string
for _, cl := range credSources {
clIds = append(clIds, cl.PublicId)
credLibraries = append(credLibraries, &target.CredentialLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: cl.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
})
credLibIds = append(credLibIds, cl.PublicId)
}
type args struct {
@@ -392,11 +401,22 @@ func TestRepository_UpdateTcpTarget(t *testing.T) {
cls := vault.TestCredentialLibraries(t, conn, wrapper, cs.GetPublicId(), 5)
var testClIds []string
var testCredLibs []*target.CredentialLibrary
for _, cl := range cls {
testCredLibs = append(testCredLibs, &target.CredentialLibrary{
CredentialLibrary: &store.CredentialLibrary{
CredentialLibraryId: cl.PublicId,
CredentialPurpose: string(credential.ApplicationPurpose),
},
})
testClIds = append(testClIds, cl.PublicId)
}
tt.newTargetOpts = append(tt.newTargetOpts, target.WithHostSources(testHostSetIds), target.WithCredentialSources(testClIds))
tt.newTargetOpts = append(
tt.newTargetOpts,
target.WithHostSources(testHostSetIds),
target.WithCredentialLibraries(testCredLibs),
)
name := tt.newName
if name == "" {
name = tcp.TestId(t)
+5 -6
View File
@@ -36,12 +36,11 @@ func TestTarget(t *testing.T, conn *db.DB, scopeId, name string, opt ...target.O
err := rw.CreateItems(context.Background(), newHostSets)
require.NoError(err)
}
if len(opts.WithCredentialSources) > 0 {
newCredLibs := make([]interface{}, 0, len(opts.WithCredentialSources))
for _, cl := range opts.WithCredentialSources {
newCl, err := target.NewCredentialLibrary(tar.PublicId, cl)
require.NoError(err)
newCredLibs = append(newCredLibs, newCl)
if len(opts.WithCredentialLibraries) > 0 {
newCredLibs := make([]interface{}, 0, len(opts.WithCredentialLibraries))
for _, cl := range opts.WithCredentialLibraries {
cl.TargetId = tar.PublicId
newCredLibs = append(newCredLibs, cl)
}
err := rw.CreateItems(context.Background(), newCredLibs)
require.NoError(err)
+18 -4
View File
@@ -4,19 +4,33 @@ import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/target/store"
"github.com/stretchr/testify/require"
)
// TestNewCredentialLibrary creates a new in memory CredentialLibrary
// representing the relationship between targetId and credentialLibraryId with
// the given purpose.
func TestNewCredentialLibrary(targetId, credentialLibraryId string, purpose credential.Purpose) *CredentialLibrary {
return &CredentialLibrary{
CredentialLibrary: &store.CredentialLibrary{
TargetId: targetId,
CredentialLibraryId: credentialLibraryId,
CredentialPurpose: string(purpose),
},
}
}
// TestCredentialLibrary creates a CredentialLibrary for targetId and
// libraryId.
// libraryId with the credential purpose of application.
func TestCredentialLibrary(t *testing.T, conn *db.DB, targetId, libraryId string) *CredentialLibrary {
t.Helper()
require := require.New(t)
rw := db.New(conn)
lib, err := NewCredentialLibrary(targetId, libraryId)
require.NoError(err)
err = rw.Create(context.Background(), lib)
lib := TestNewCredentialLibrary(targetId, libraryId, credential.ApplicationPurpose)
err := rw.Create(context.Background(), lib)
require.NoError(err)
return lib
}
+1 -1
View File
@@ -7,7 +7,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/hashicorp/eventlogger v0.1.0
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v0.16.2
github.com/hashicorp/go-kms-wrapping v0.6.6
+2 -2
View File
@@ -243,8 +243,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/eventlogger v0.1.0 h1:S6xc4gZVzewuDUP4R4Ngko419h/CGDuV/b4ADL3XLik=
github.com/hashicorp/eventlogger v0.1.0/go.mod h1:a3IXf1aEJfpCPzseTOrwKj4fVW/Qn3oEmpQeaIznzH0=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5 h1:kNkH4G6zzWlZSoI1I+B/ud4chVKTPL516C6jB7dRdlE=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.5/go.mod h1:8rcez7Kw1zanB0/074qnOuGu7zxmNh9Xr2ZI+K4xVIA=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239 h1:Yh9tY0lige+y0trmjQeT9NRDo6+YvtNAzbmUNOsIUzI=
github.com/hashicorp/eventlogger/filters/encrypt v0.1.6-0.20211027211326-5db60a48f239/go.mod h1:8rcez7Kw1zanB0/074qnOuGu7zxmNh9Xr2ZI+K4xVIA=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
@@ -9,6 +9,7 @@ import (
"github.com/hashicorp/boundary/sdk/pbs/controller/api"
"github.com/hashicorp/boundary/sdk/wrapper"
"github.com/hashicorp/eventlogger"
"github.com/hashicorp/eventlogger/filters/encrypt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"
@@ -92,7 +93,7 @@ func TestAuthMethod_Tags(t *testing.T) {
"account_claim_maps": structpb.NewStringValue("public-account_claim_maps"),
"disable_discovered_config_validation": structpb.NewStringValue("public-disable_discovered_config_validation"),
"dry_run": structpb.NewStringValue("public-dry_run"),
"client_secret": structpb.NewStringValue("<REDACTED>"),
"client_secret": structpb.NewStringValue(encrypt.RedactedData),
},
},
AuthorizedActions: []string{"action-1", "action-2"},
@@ -487,6 +487,10 @@ type Target struct {
ApplicationCredentialSourceIds []string `protobuf:"bytes,400,rep,name=application_credential_source_ids,proto3" json:"application_credential_source_ids,omitempty"`
// Output only. The application credential sources associated with this Target.
ApplicationCredentialSources []*CredentialSource `protobuf:"bytes,410,rep,name=application_credential_sources,proto3" json:"application_credential_sources,omitempty"`
// Output only. The IDs of the egress credential source ids associated with this Target.
EgressCredentialSourceIds []string `protobuf:"bytes,500,rep,name=egress_credential_source_ids,proto3" json:"egress_credential_source_ids,omitempty"`
// Output only. The egress credential sources associated with this Target.
EgressCredentialSources []*CredentialSource `protobuf:"bytes,510,rep,name=egress_credential_sources,proto3" json:"egress_credential_sources,omitempty"`
// The attributes that are applicable for the specific Target.
Attributes *structpb.Struct `protobuf:"bytes,200,opt,name=attributes,proto3" json:"attributes,omitempty"`
// Output only. The available actions on this resource for this user.
@@ -667,6 +671,20 @@ func (x *Target) GetApplicationCredentialSources() []*CredentialSource {
return nil
}
func (x *Target) GetEgressCredentialSourceIds() []string {
if x != nil {
return x.EgressCredentialSourceIds
}
return nil
}
func (x *Target) GetEgressCredentialSources() []*CredentialSource {
if x != nil {
return x.EgressCredentialSources
}
return nil
}
func (x *Target) GetAttributes() *structpb.Struct {
if x != nil {
return x.Attributes
@@ -1130,7 +1148,7 @@ var file_controller_api_resources_targets_v1_target_proto_rawDesc = []byte{
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, 0x53, 0x65, 0x63, 0x72, 0x65,
0x74, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0xe9, 0x0c, 0x0a, 0x06, 0x54, 0x61,
0x74, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0xa4, 0x0e, 0x0a, 0x06, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64,
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64,
@@ -1226,92 +1244,104 @@ var file_controller_api_resources_targets_v1_target_proto_rawDesc = []byte{
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x52, 0x1e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
0x65, 0x73, 0x18, 0xc8, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75,
0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28,
0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x13, 0x54, 0x63, 0x70, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x0a,
0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0a, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x42, 0x2e, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x26, 0x0a, 0x17, 0x61, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f,
0x70, 0x6f, 0x72, 0x74, 0x12, 0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72,
0x74, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x22,
0x26, 0x0a, 0x0a, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a,
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xed, 0x03, 0x0a, 0x18, 0x53, 0x65, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x44, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x5f, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69,
0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x2d, 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, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x28, 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, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x50, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x63,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18,
0x5a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x78, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65,
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x70, 0x72, 0x69,
0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x82, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07,
0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x8c, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
0x6e, 0x74, 0x18, 0x8d, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x6e,
0x66, 0x6f, 0x18, 0x96, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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,
0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b,
0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0xeb, 0x03, 0x0a, 0x14, 0x53, 0x65, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64,
0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x43,
0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
0x72, 0x63, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x1c, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x63,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x5f, 0x69, 0x64, 0x73, 0x18, 0xf4, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1c, 0x65, 0x67, 0x72,
0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x74, 0x0a, 0x19, 0x65, 0x67, 0x72,
0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0xfe, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 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, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63,
0x6f, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x18, 0x28, 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, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74,
0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x32,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x12, 0x20, 0x0a,
0x0b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x3c, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x12,
0x18, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09,
0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70,
0x65, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a,
0x13, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0b, 0x63,
0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x6e, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x36, 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, 0x43, 0x72,
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x73, 0x42, 0x50, 0x5a, 0x4e, 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, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 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, 0x3b,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x52, 0x19, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x72, 0x65,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12,
0x3e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0xc8, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0,
0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x22, 0x87, 0x01, 0x0a, 0x13, 0x54, 0x63, 0x70, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2e, 0xa0, 0xda,
0x29, 0x01, 0xc2, 0xdd, 0x29, 0x26, 0x0a, 0x17, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
0x65, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x12,
0x0b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0c, 0x64, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x26, 0x0a, 0x0a, 0x57, 0x6f,
0x72, 0x6b, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x22, 0xed, 0x03, 0x0a, 0x18, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12,
0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12,
0x1c, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a,
0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69,
0x6d, 0x65, 0x18, 0x28, 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, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69,
0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x50, 0x20, 0x01, 0x28, 0x09,
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x05,
0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x6d,
0x69, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x65, 0x18, 0x78, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f,
0x6b, 0x65, 0x79, 0x18, 0x82, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x76,
0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f,
0x69, 0x64, 0x18, 0x8c, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49,
0x64, 0x12, 0x1b, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x8d, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x52,
0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x96, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x57, 0x6f, 0x72, 0x6b, 0x65,
0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x6e,
0x66, 0x6f, 0x22, 0xeb, 0x03, 0x0a, 0x14, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f,
0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63,
0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x3e,
0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x28,
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, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18,
0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52,
0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x6f, 0x73, 0x74,
0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68,
0x6f, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x6f,
0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x6f, 0x73,
0x74, 0x5f, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x50, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e,
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e,
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x6e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 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, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x61, 0x6c, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
0x42, 0x50, 0x5a, 0x4e, 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, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 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, 0x3b, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1363,19 +1393,20 @@ var file_controller_api_resources_targets_v1_target_proto_depIdxs = []int32{
13, // 13: controller.api.resources.targets.v1.Target.worker_filter:type_name -> google.protobuf.StringValue
3, // 14: controller.api.resources.targets.v1.Target.application_credential_libraries:type_name -> controller.api.resources.targets.v1.CredentialLibrary
2, // 15: controller.api.resources.targets.v1.Target.application_credential_sources:type_name -> controller.api.resources.targets.v1.CredentialSource
11, // 16: controller.api.resources.targets.v1.Target.attributes:type_name -> google.protobuf.Struct
15, // 17: controller.api.resources.targets.v1.TcpTargetAttributes.default_port:type_name -> google.protobuf.UInt32Value
12, // 18: controller.api.resources.targets.v1.SessionAuthorizationData.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
14, // 19: controller.api.resources.targets.v1.SessionAuthorizationData.created_time:type_name -> google.protobuf.Timestamp
8, // 20: controller.api.resources.targets.v1.SessionAuthorizationData.worker_info:type_name -> controller.api.resources.targets.v1.WorkerInfo
12, // 21: controller.api.resources.targets.v1.SessionAuthorization.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
14, // 22: controller.api.resources.targets.v1.SessionAuthorization.created_time:type_name -> google.protobuf.Timestamp
5, // 23: controller.api.resources.targets.v1.SessionAuthorization.credentials:type_name -> controller.api.resources.targets.v1.SessionCredential
24, // [24:24] is the sub-list for method output_type
24, // [24:24] is the sub-list for method input_type
24, // [24:24] is the sub-list for extension type_name
24, // [24:24] is the sub-list for extension extendee
0, // [0:24] is the sub-list for field type_name
2, // 16: controller.api.resources.targets.v1.Target.egress_credential_sources:type_name -> controller.api.resources.targets.v1.CredentialSource
11, // 17: controller.api.resources.targets.v1.Target.attributes:type_name -> google.protobuf.Struct
15, // 18: controller.api.resources.targets.v1.TcpTargetAttributes.default_port:type_name -> google.protobuf.UInt32Value
12, // 19: controller.api.resources.targets.v1.SessionAuthorizationData.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
14, // 20: controller.api.resources.targets.v1.SessionAuthorizationData.created_time:type_name -> google.protobuf.Timestamp
8, // 21: controller.api.resources.targets.v1.SessionAuthorizationData.worker_info:type_name -> controller.api.resources.targets.v1.WorkerInfo
12, // 22: controller.api.resources.targets.v1.SessionAuthorization.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
14, // 23: controller.api.resources.targets.v1.SessionAuthorization.created_time:type_name -> google.protobuf.Timestamp
5, // 24: controller.api.resources.targets.v1.SessionAuthorization.credentials:type_name -> controller.api.resources.targets.v1.SessionCredential
25, // [25:25] is the sub-list for method output_type
25, // [25:25] is the sub-list for method input_type
25, // [25:25] is the sub-list for extension type_name
25, // [25:25] is the sub-list for extension extendee
0, // [0:25] is the sub-list for field type_name
}
func init() { file_controller_api_resources_targets_v1_target_proto_init() }
+6 -4
View File
@@ -8,6 +8,7 @@ IMAGE_NAME=postgres
IMAGE_TAG ?= $(REGISTRY_NAME)/$(IMAGE_NAME):11-alpine
PG_OPTS ?=
TEST_DB_PORT ?= 5432
TEST_CONTAINER_NAME ?= boundary-sql-tests
# Generate targets from dockerfiles
dockerfiles = $(wildcard Dockerfile.*)
@@ -29,7 +30,7 @@ database-up:
@echo "Additional postgres configuration: $(PG_OPTS)"
@docker run \
$(DOCKER_ARGS) \
--name boundary-sql-tests \
--name $(TEST_CONTAINER_NAME) \
-p $(TEST_DB_PORT):5432 \
-e POSTGRES_PASSWORD=boundary \
-e POSTGRES_USER=boundary \
@@ -40,11 +41,12 @@ database-up:
$(IMAGE_TAG) \
-c 'config_file=/etc/postgresql/postgresql.conf' \
$(PG_OPTS) 1> /dev/null
@echo "Container name: $(TEST_CONTAINER_NAME)"
@echo "Test database available at: 127.0.0.1:$(TEST_DB_PORT)"
@echo "For database logs run:"
@echo " docker logs boundary-sql-tests"
@echo " docker logs $(TEST_CONTAINER_NAME)"
clean:
docker stop boundary-sql-tests || true
docker rm -v boundary-sql-tests || true
docker stop $(TEST_CONTAINER_NAME) || true
docker rm -v $(TEST_CONTAINER_NAME) || true
.PHONY: all docker-build database-up ${docker-builds} ${docker-publishes} clean
+15 -15
View File
@@ -31,7 +31,7 @@
"@hashicorp/react-product-features-list": "^5.0.0",
"@hashicorp/react-search": "^6.1.1",
"@hashicorp/react-section-header": "^5.0.4",
"@hashicorp/react-subnav": "^9.0.1",
"@hashicorp/react-subnav": "^9.1.4",
"@hashicorp/react-use-cases": "^5.0.0",
"@hashicorp/react-vertical-text-block-list": "^7.0.0",
"change-case": "4.1.2",
@@ -1143,9 +1143,9 @@
}
},
"node_modules/@hashicorp/react-button": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@hashicorp/react-button/-/react-button-6.0.1.tgz",
"integrity": "sha512-e5Kl0Nc0V9RWxrNUrig2BQlJuwTmJeZdCZJkOcUGbCwySgQ1otWkKjLRR2nOGM3v+EAkkBxhMiyBIRS2vPNrdg==",
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@hashicorp/react-button/-/react-button-6.0.3.tgz",
"integrity": "sha512-CRK93cWw5ap4tGGvMoyr/Ydvvz1Ie1RTyTdBhcpARlH7pCIAmvxHKMK+FCWXWGJNjpM9suKenXfdTJRfz7+KNw==",
"dependencies": {
"@hashicorp/platform-product-meta": "^0.1.0",
"@hashicorp/react-inline-svg": "^6.0.1",
@@ -1603,13 +1603,13 @@
}
},
"node_modules/@hashicorp/react-subnav": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@hashicorp/react-subnav/-/react-subnav-9.0.1.tgz",
"integrity": "sha512-WRfCrkGD55qMnww+L2+tdXF04/NRY7F8XAuKqRpLpCk6ygHFvsxlsc4sn5TXpKPEPZCdcT22qlxvejjOyJ3E4g==",
"version": "9.1.4",
"resolved": "https://registry.npmjs.org/@hashicorp/react-subnav/-/react-subnav-9.1.4.tgz",
"integrity": "sha512-osbb+LzDwBRYp2IBHqjHpJXRIRFiDrMkRHw0k4DsAvb/3ZzUXD0EUqSXJGjjPxzC8m6/bsFXQnxcNUrFMshBZA==",
"dependencies": {
"@hashicorp/mktg-logos": "^1.0.2",
"@hashicorp/platform-product-meta": "^0.1.0",
"@hashicorp/react-button": "^6.0.0",
"@hashicorp/react-button": "^6.0.3",
"@hashicorp/react-inline-svg": "^6.0.3",
"@hashicorp/react-link-wrap": "^3.0.3",
"@reach/visually-hidden": "^0.16.0",
@@ -21221,9 +21221,9 @@
}
},
"@hashicorp/react-button": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@hashicorp/react-button/-/react-button-6.0.1.tgz",
"integrity": "sha512-e5Kl0Nc0V9RWxrNUrig2BQlJuwTmJeZdCZJkOcUGbCwySgQ1otWkKjLRR2nOGM3v+EAkkBxhMiyBIRS2vPNrdg==",
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@hashicorp/react-button/-/react-button-6.0.3.tgz",
"integrity": "sha512-CRK93cWw5ap4tGGvMoyr/Ydvvz1Ie1RTyTdBhcpARlH7pCIAmvxHKMK+FCWXWGJNjpM9suKenXfdTJRfz7+KNw==",
"requires": {
"@hashicorp/platform-product-meta": "^0.1.0",
"@hashicorp/react-inline-svg": "^6.0.1",
@@ -21597,13 +21597,13 @@
}
},
"@hashicorp/react-subnav": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@hashicorp/react-subnav/-/react-subnav-9.0.1.tgz",
"integrity": "sha512-WRfCrkGD55qMnww+L2+tdXF04/NRY7F8XAuKqRpLpCk6ygHFvsxlsc4sn5TXpKPEPZCdcT22qlxvejjOyJ3E4g==",
"version": "9.1.4",
"resolved": "https://registry.npmjs.org/@hashicorp/react-subnav/-/react-subnav-9.1.4.tgz",
"integrity": "sha512-osbb+LzDwBRYp2IBHqjHpJXRIRFiDrMkRHw0k4DsAvb/3ZzUXD0EUqSXJGjjPxzC8m6/bsFXQnxcNUrFMshBZA==",
"requires": {
"@hashicorp/mktg-logos": "^1.0.2",
"@hashicorp/platform-product-meta": "^0.1.0",
"@hashicorp/react-button": "^6.0.0",
"@hashicorp/react-button": "^6.0.3",
"@hashicorp/react-inline-svg": "^6.0.3",
"@hashicorp/react-link-wrap": "^3.0.3",
"@reach/visually-hidden": "^0.16.0",
+1 -1
View File
@@ -27,7 +27,7 @@
"@hashicorp/react-product-features-list": "^5.0.0",
"@hashicorp/react-search": "^6.1.1",
"@hashicorp/react-section-header": "^5.0.4",
"@hashicorp/react-subnav": "^9.0.1",
"@hashicorp/react-subnav": "^9.1.4",
"@hashicorp/react-use-cases": "^5.0.0",
"@hashicorp/react-vertical-text-block-list": "^7.0.0",
"change-case": "4.1.2",