Add secrets_hmac to host catalog output (#1712)
Co-authored-by: Jim <jlambert@hashicorp.com>
This commit is contained in:
1 parent
063b613bd1
commit
866bfceefc
24 files changed
+520
-179
No files matched your search
@@ -27,6 +27,7 @@ type HostCatalog struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
Secrets map[string]interface{} `json:"secrets,omitempty"`
|
||||
SecretsHmac string `json:"secrets_hmac,omitempty"`
|
||||
AuthorizedActions []string `json:"authorized_actions,omitempty"`
|
||||
AuthorizedCollectionActions map[string][]string `json:"authorized_collection_actions,omitempty"`
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ const (
|
||||
PluginNameField = "plugin_name"
|
||||
IpAddressesField = "ip_addresses"
|
||||
DnsNamesField = "dns_names"
|
||||
SecretsHmacField = "secrets_hmac"
|
||||
ExternalIdField = "external_id"
|
||||
EgressCredentialSourceIdsField = "egress_credential_source_ids"
|
||||
EgressCredentialSourcesField = "egress_credential_sources"
|
||||
|
||||
@@ -146,6 +146,9 @@ func printItemTable(result api.GenericResult) string {
|
||||
if item.Type != "" {
|
||||
nonAttributeMap["Type"] = item.Type
|
||||
}
|
||||
if item.SecretsHmac != "" {
|
||||
nonAttributeMap["Secrets HMAC"] = item.SecretsHmac
|
||||
}
|
||||
|
||||
maxLength := base.MaxAttributesLength(nonAttributeMap, item.Attributes, keySubstMap)
|
||||
|
||||
|
||||
+22
-19
@@ -508,24 +508,24 @@ func (rw *Db) CreateItems(ctx context.Context, createItems []interface{}, opt ..
|
||||
|
||||
// Update an object in the db, fieldMask is required and provides
|
||||
// field_mask.proto paths for fields that should be updated. The i interface
|
||||
// parameter is the type the caller wants to update in the db and its
|
||||
// fields are set to the update values. setToNullPaths is optional and
|
||||
// provides field_mask.proto paths for the fields that should be set to
|
||||
// null. fieldMaskPaths and setToNullPaths must not intersect. The caller
|
||||
// is responsible for the transaction life cycle of the writer and if an
|
||||
// error is returned the caller must decide what to do with the transaction,
|
||||
// which almost always should be to rollback. Update returns the number of
|
||||
// rows updated.
|
||||
// parameter is the type the caller wants to update in the db and its fields are
|
||||
// set to the update values. setToNullPaths is optional and provides
|
||||
// field_mask.proto paths for the fields that should be set to null.
|
||||
// fieldMaskPaths and setToNullPaths must not intersect. The caller is
|
||||
// responsible for the transaction life cycle of the writer and if an error is
|
||||
// returned the caller must decide what to do with the transaction, which almost
|
||||
// always should be to rollback. Update returns the number of rows updated.
|
||||
//
|
||||
// Supported options: WithOplog, NewOplogMsg, WithWhere and WithVersion.
|
||||
// WithOplog will write an oplog entry for the update. NewOplogMsg
|
||||
// will return in-memory oplog message. WithOplog and NewOplogMsg cannot be
|
||||
// used together. If WithVersion is used, then the update will include the
|
||||
// version number in the update where clause, which basically makes the update
|
||||
// use optimistic locking and the update will only succeed if the existing rows
|
||||
// version matches the WithVersion option. Zero is not a valid value for the
|
||||
// Supported options: WithOplog, NewOplogMsg, WithWhere, WithDebug, and
|
||||
// WithVersion. WithOplog will write an oplog entry for the update. NewOplogMsg
|
||||
// will return in-memory oplog message. WithOplog and NewOplogMsg cannot be used
|
||||
// together. If WithVersion is used, then the update will include the version
|
||||
// number in the update where clause, which basically makes the update use
|
||||
// optimistic locking and the update will only succeed if the existing rows
|
||||
// version matches the WithVersion option. Zero is not a valid value for the
|
||||
// WithVersion option and will return an error. WithWhere allows specifying an
|
||||
// additional constraint on the operation in addition to the PKs.
|
||||
// additional constraint on the operation in addition to the PKs. WithDebug will
|
||||
// turn on debugging for the update call.
|
||||
func (rw *Db) Update(ctx context.Context, i interface{}, fieldMaskPaths []string, setToNullPaths []string, opt ...Option) (int, error) {
|
||||
const op = "db.Update"
|
||||
if rw.underlying == nil {
|
||||
@@ -603,16 +603,19 @@ func (rw *Db) Update(ctx context.Context, i interface{}, fieldMaskPaths []string
|
||||
return NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket"))
|
||||
}
|
||||
}
|
||||
var underlying *gorm.DB
|
||||
underlying := rw.underlying.Model(i)
|
||||
if opts.withDebug {
|
||||
underlying = underlying.Debug()
|
||||
}
|
||||
switch {
|
||||
case opts.WithVersion != nil || opts.withWhereClause != "":
|
||||
where, args, err := rw.whereClausesFromOpts(ctx, i, opts)
|
||||
if err != nil {
|
||||
return NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
underlying = rw.underlying.Model(i).Where(where, args...).Updates(updateFields)
|
||||
underlying = underlying.Where(where, args...).Updates(updateFields)
|
||||
default:
|
||||
underlying = rw.underlying.Model(i).Updates(updateFields)
|
||||
underlying = underlying.Updates(updateFields)
|
||||
}
|
||||
if underlying.Error != nil {
|
||||
if underlying.Error == gorm.ErrRecordNotFound {
|
||||
|
||||
@@ -30,8 +30,7 @@ create view host_plugin_host_set_with_value_obj as
|
||||
comment on view host_plugin_host_set_with_value_obj is
|
||||
'host plugin host set with its associated value objects';
|
||||
|
||||
-- host_plugin_catalog_with_secret is useful for reading a plugin catalog with
|
||||
-- its associated persisted data.
|
||||
-- REPLACED in 10_plugin_host_secrets_hmac.up.sql
|
||||
create view host_plugin_catalog_with_secret as
|
||||
select
|
||||
hc.public_id,
|
||||
|
||||
@@ -6,12 +6,11 @@ alter table host_plugin_host
|
||||
create trigger update_version_column after update on host_plugin_host
|
||||
for each row execute procedure update_version_column();
|
||||
|
||||
drop view host_plugin_host_with_value_obj_and_set_memberships;
|
||||
|
||||
-- host_plugin_host_with_value_obj_and_set_memberships is useful for reading a
|
||||
-- plugin host with its associated value objects (ip addresses, dns names) and
|
||||
-- set membership as columns with delimited values. The delimiter depends on
|
||||
-- the value objects (e.g. if they need ordering).
|
||||
drop view host_plugin_host_with_value_obj_and_set_memberships;
|
||||
create view host_plugin_host_with_value_obj_and_set_memberships as
|
||||
select
|
||||
h.public_id,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
begin;
|
||||
|
||||
alter table host_plugin_catalog
|
||||
add column secrets_hmac bytea
|
||||
constraint secrets_hmac_null_or_not_empty
|
||||
check(secrets_hmac is null or length(secrets_hmac) > 0);
|
||||
|
||||
-- host_plugin_catalog_with_secret is useful for reading a plugin catalog with
|
||||
-- its associated persisted data.
|
||||
drop view host_plugin_catalog_with_secret;
|
||||
create view host_plugin_catalog_with_secret as
|
||||
select
|
||||
hc.public_id,
|
||||
hc.scope_id,
|
||||
hc.plugin_id,
|
||||
hc.name,
|
||||
hc.description,
|
||||
hc.create_time,
|
||||
hc.update_time,
|
||||
hc.version,
|
||||
hc.secrets_hmac,
|
||||
hc.attributes,
|
||||
hcs.secret,
|
||||
hcs.key_id,
|
||||
hcs.create_time as persisted_create_time,
|
||||
hcs.update_time as persisted_update_time
|
||||
from
|
||||
host_plugin_catalog hc
|
||||
left outer join host_plugin_catalog_secret hcs on hc.public_id = hcs.catalog_id;
|
||||
comment on view host_plugin_catalog_with_secret is
|
||||
'host plugin catalog with its associated persisted data';
|
||||
|
||||
commit;
|
||||
@@ -4146,6 +4146,11 @@
|
||||
"type": "object",
|
||||
"description": "Secrets specific to the catalog type. These are never output."
|
||||
},
|
||||
"secrets_hmac": {
|
||||
"type": "string",
|
||||
"description": "Output only. The HMAC of the last secrets supplied via the API, if any.",
|
||||
"readOnly": true
|
||||
},
|
||||
"authorized_actions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
@@ -5,11 +5,14 @@ package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/libs/crypto"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
@@ -42,6 +45,7 @@ func NewHostCatalog(ctx context.Context, scopeId, pluginId string, opt ...Option
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
Attributes: attrs,
|
||||
SecretsHmac: opts.withSecretsHmac,
|
||||
},
|
||||
Secrets: opts.withSecrets,
|
||||
}
|
||||
@@ -54,6 +58,35 @@ func allocHostCatalog() *HostCatalog {
|
||||
}
|
||||
}
|
||||
|
||||
// hmacSecrets before writing it to the db
|
||||
func (c *HostCatalog) hmacSecrets(ctx context.Context, cipher wrapping.Wrapper) error {
|
||||
const op = "plugin.(HostCatalog).hmacSecrets"
|
||||
if c.Secrets == nil {
|
||||
c.SecretsHmac = nil
|
||||
return nil
|
||||
}
|
||||
secretsMap := c.Secrets.AsMap()
|
||||
if len(secretsMap) == 0 {
|
||||
c.SecretsHmac = nil
|
||||
return nil
|
||||
}
|
||||
if cipher == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "missing cipher")
|
||||
}
|
||||
// Go's JSON encoding is stable (that is, it alphabetizes keys) so it's a
|
||||
// good option to produce an HMAC-able string.
|
||||
jsonSecrets, err := json.Marshal(secretsMap)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Code(errors.Encryption)))
|
||||
}
|
||||
hm, err := crypto.HmacSha256(ctx, jsonSecrets, cipher, []byte(c.PublicId), nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithCode(errors.Code(errors.Encryption)))
|
||||
}
|
||||
c.SecretsHmac = []byte(hm)
|
||||
return nil
|
||||
}
|
||||
|
||||
// clone provides a deep copy of the HostCatalog with the exception of the
|
||||
// secret. The secret shallow copied.
|
||||
func (c *HostCatalog) clone() *HostCatalog {
|
||||
@@ -107,6 +140,7 @@ type catalogAgg struct {
|
||||
CreateTime *timestamp.Timestamp
|
||||
UpdateTime *timestamp.Timestamp
|
||||
Version uint32
|
||||
SecretsHmac []byte
|
||||
Attributes []byte
|
||||
Secret []byte
|
||||
KeyId string
|
||||
@@ -127,6 +161,7 @@ func (agg *catalogAgg) toCatalogAndPersisted() (*HostCatalog, *HostCatalogSecret
|
||||
c.CreateTime = agg.CreateTime
|
||||
c.UpdateTime = agg.UpdateTime
|
||||
c.Version = agg.Version
|
||||
c.SecretsHmac = agg.SecretsHmac
|
||||
c.Attributes = agg.Attributes
|
||||
|
||||
var s *HostCatalogSecret
|
||||
|
||||
@@ -9,7 +9,11 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/plugin/host"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/hashicorp/go-kms-wrapping/wrappers/aead"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -326,3 +330,114 @@ func TestHostCatalog_SetTableName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostCatalog_SecretsHmac(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rootWrapper := db.TestWrapper(t)
|
||||
kmsCache := kms.TestKms(t, conn, rootWrapper)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, rootWrapper))
|
||||
databaseWrapper, err := kmsCache.GetWrapper(ctx, prj.PublicId, kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
|
||||
plg := host.TestPlugin(t, conn, "testplugin")
|
||||
cat := TestCatalog(t, conn, prj.GetPublicId(), plg.GetPublicId())
|
||||
|
||||
// stableValue checks that HMACing the same value returns the same result.
|
||||
// The first time it's called to match it will be empty and thus assign the
|
||||
// expected value; the second time it will assert that value.
|
||||
var stableValue string
|
||||
tests := []struct {
|
||||
name string
|
||||
hcFn func() *HostCatalog
|
||||
hmacWrapper wrapping.Wrapper
|
||||
emptyHmac bool
|
||||
matchStableValue bool
|
||||
wantHmacErrMatch *errors.Template
|
||||
}{
|
||||
{
|
||||
name: "valid-empty-secrets",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = nil
|
||||
cat.SecretsHmac = []byte("foobar")
|
||||
return cat
|
||||
},
|
||||
emptyHmac: true,
|
||||
hmacWrapper: databaseWrapper,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = mustStruct(map[string]interface{}{"foo": "bar"})
|
||||
cat.SecretsHmac = nil
|
||||
return cat
|
||||
},
|
||||
hmacWrapper: databaseWrapper,
|
||||
matchStableValue: true,
|
||||
},
|
||||
{
|
||||
name: "valid-different-val",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = mustStruct(map[string]interface{}{"zip": "zap"})
|
||||
cat.SecretsHmac = nil
|
||||
return cat
|
||||
},
|
||||
hmacWrapper: databaseWrapper,
|
||||
},
|
||||
{
|
||||
name: "valid-original-val",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = mustStruct(map[string]interface{}{"foo": "bar"})
|
||||
cat.SecretsHmac = nil
|
||||
return cat
|
||||
},
|
||||
hmacWrapper: databaseWrapper,
|
||||
matchStableValue: true,
|
||||
},
|
||||
{
|
||||
name: "hmac-missing-wrapper",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = mustStruct(map[string]interface{}{"foo": "bar"})
|
||||
cat.SecretsHmac = []byte("foobar")
|
||||
return cat
|
||||
},
|
||||
wantHmacErrMatch: errors.T(errors.InvalidParameter),
|
||||
},
|
||||
{
|
||||
name: "hmac-bad-wrapper",
|
||||
hcFn: func() *HostCatalog {
|
||||
cat.Secrets = mustStruct(map[string]interface{}{"foo": "bar"})
|
||||
cat.SecretsHmac = nil
|
||||
return cat
|
||||
},
|
||||
hmacWrapper: &aead.Wrapper{},
|
||||
wantHmacErrMatch: errors.T(errors.InvalidParameter),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
hmacCat := tt.hcFn().clone()
|
||||
err = hmacCat.hmacSecrets(ctx, tt.hmacWrapper)
|
||||
if tt.wantHmacErrMatch != nil {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
if tt.emptyHmac {
|
||||
assert.Empty(hmacCat.SecretsHmac)
|
||||
stableValue = ""
|
||||
return
|
||||
}
|
||||
assert.NotEmpty(hmacCat.SecretsHmac)
|
||||
if tt.matchStableValue {
|
||||
if stableValue == "" {
|
||||
stableValue = base58.Encode(hmacCat.SecretsHmac)
|
||||
} else {
|
||||
assert.Equal(stableValue, base58.Encode(hmacCat.SecretsHmac))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ type options struct {
|
||||
withDnsNames []string
|
||||
withLimit int
|
||||
withSetIds []string
|
||||
withSecretsHmac []byte
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
@@ -122,3 +123,10 @@ func WithSetIds(with []string) Option {
|
||||
o.withSetIds = with
|
||||
}
|
||||
}
|
||||
|
||||
// WithSecretsHmac provides an optional HMAC of secrets. Used for testing.
|
||||
func WithSecretsHmac(secretsHmac []byte) Option {
|
||||
return func(o *options) {
|
||||
o.withSecretsHmac = secretsHmac
|
||||
}
|
||||
}
|
||||
@@ -68,4 +68,10 @@ func Test_GetOpts(t *testing.T) {
|
||||
testOpts.withSetIds = []string{"foo"}
|
||||
assert.EqualValues(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithSecretsHmac", func(t *testing.T) {
|
||||
opts := getOpts(WithSecretsHmac([]byte("secrets-hmac")))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withSecretsHmac = []byte("secrets-hmac")
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
pbset "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/mr-tron/base58"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -68,6 +69,17 @@ func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, _ ...Opt
|
||||
return nil, nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
// If secrets were passed in, HMAC 'em
|
||||
if c.Secrets != nil && len(c.Secrets.GetFields()) > 0 {
|
||||
databaseWrapper, err := r.kms.GetWrapper(ctx, c.ScopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
|
||||
}
|
||||
if err := c.hmacSecrets(ctx, databaseWrapper); err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("error hmac'ing passed-in secrets"))
|
||||
}
|
||||
}
|
||||
|
||||
plgHc, err := toPluginCatalog(ctx, c)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op)
|
||||
@@ -226,6 +238,7 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version
|
||||
newCatalog := currentCatalog.clone()
|
||||
var updateAttributes bool
|
||||
var dbMask, nullFields []string
|
||||
var alreadySetSecrets bool
|
||||
for _, f := range fieldMask {
|
||||
switch {
|
||||
case strings.EqualFold("name", f) && c.Name == "":
|
||||
@@ -245,10 +258,29 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version
|
||||
// sent, we only need to do this once.
|
||||
updateAttributes = true
|
||||
case strings.EqualFold("secrets", strings.Split(f, ".")[0]):
|
||||
if alreadySetSecrets {
|
||||
continue
|
||||
}
|
||||
alreadySetSecrets = true
|
||||
// While in a similar format, secrets are passed along
|
||||
// wholesale (for the time being). Don't append this mask
|
||||
// field, as secrets do not have a database entry.
|
||||
newCatalog.Secrets = c.Secrets
|
||||
switch {
|
||||
case newCatalog.Secrets == nil,
|
||||
len(newCatalog.Secrets.GetFields()) == 0:
|
||||
nullFields = append(nullFields, "SecretsHmac")
|
||||
default:
|
||||
// If secrets were passed in, HMAC 'em
|
||||
databaseWrapper, err := r.kms.GetWrapper(ctx, c.ScopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
|
||||
}
|
||||
if err := newCatalog.hmacSecrets(ctx, databaseWrapper); err != nil {
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("error hmac'ing passed-in secrets"))
|
||||
}
|
||||
dbMask = append(dbMask, "SecretsHmac")
|
||||
}
|
||||
default:
|
||||
return nil, nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, fmt.Sprintf("invalid field mask: %s", f))
|
||||
}
|
||||
@@ -639,6 +671,9 @@ func toPluginCatalog(ctx context.Context, in *HostCatalog) (*pb.HostCatalog, err
|
||||
Name: name,
|
||||
Description: description,
|
||||
}
|
||||
if len(in.GetSecretsHmac()) > 0 {
|
||||
hc.SecretsHmac = base58.Encode(in.GetSecretsHmac())
|
||||
}
|
||||
if in.GetAttributes() != nil {
|
||||
attrs := &structpb.Struct{}
|
||||
if err := proto.Unmarshal(in.GetAttributes(), attrs); err != nil {
|
||||
|
||||
@@ -576,6 +576,18 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
checkSecretsHmac := func(notNil bool) checkFunc {
|
||||
return func(t *testing.T, ctx context.Context) {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
if notNil {
|
||||
assert.NotEmpty(gotCatalog.SecretsHmac)
|
||||
} else {
|
||||
assert.Empty(gotCatalog.SecretsHmac)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkAttributes := func(want map[string]interface{}) checkFunc {
|
||||
return func(t *testing.T, ctx context.Context) {
|
||||
t.Helper()
|
||||
@@ -804,6 +816,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"name"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentNameNil(),
|
||||
checkUpdateCatalogRequestNewName("foo"),
|
||||
checkName("foo"),
|
||||
@@ -821,6 +834,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"name"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(2), // Version remains same even though row is updated
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentNameNil(),
|
||||
checkUpdateCatalogRequestNewNameNil(),
|
||||
checkName(""),
|
||||
@@ -838,6 +852,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"name"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentNameNil(),
|
||||
checkUpdateCatalogRequestNewName(testDuplicateCatalogNameAltScope),
|
||||
checkName(testDuplicateCatalogNameAltScope),
|
||||
@@ -855,6 +870,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"description"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentDescriptionNil(),
|
||||
checkUpdateCatalogRequestNewDescription("foo"),
|
||||
checkDescription("foo"),
|
||||
@@ -872,6 +888,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"description"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(2), // Version remains same even though row is updated
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentDescriptionNil(),
|
||||
checkUpdateCatalogRequestNewDescriptionNil(),
|
||||
checkDescription(""),
|
||||
@@ -891,6 +908,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"attributes"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentAttributes(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}),
|
||||
@@ -918,6 +936,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"attributes"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentAttributes(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}),
|
||||
@@ -943,6 +962,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"attributes"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentAttributes(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}),
|
||||
@@ -965,6 +985,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"attributes.a", "attributes.foo"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentAttributes(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}),
|
||||
@@ -993,6 +1014,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"secrets.three", "secrets.five"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestPersistedSecrets(map[string]interface{}{
|
||||
"one": "two",
|
||||
}),
|
||||
@@ -1017,7 +1039,8 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
version: 2,
|
||||
fieldMask: []string{"secrets.three"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(2), // no-op
|
||||
checkVersion(3), // incremented due to secrets_hmac
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestPersistedSecrets(map[string]interface{}{
|
||||
"one": "two",
|
||||
}),
|
||||
@@ -1037,6 +1060,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"secrets"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(false),
|
||||
checkUpdateCatalogRequestPersistedSecrets(map[string]interface{}{
|
||||
"one": "two",
|
||||
}),
|
||||
@@ -1058,6 +1082,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
fieldMask: []string{"name", "secrets.three"},
|
||||
wantCheckFuncs: []checkFunc{
|
||||
checkVersion(3),
|
||||
checkSecretsHmac(true),
|
||||
checkUpdateCatalogRequestCurrentNameNil(),
|
||||
checkUpdateCatalogRequestNewName("foo"),
|
||||
checkUpdateCatalogRequestSecrets(map[string]interface{}{
|
||||
@@ -1081,22 +1106,15 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
cat := TestCatalog(t, dbConn, projectScope.PublicId, testPlugin.GetPublicId())
|
||||
// Set some (default) attributes on our test catalog
|
||||
cat.Attributes = mustMarshal(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
})
|
||||
|
||||
numCatUpdated, err := dbRW.Update(ctx, cat, []string{"attributes"}, []string{})
|
||||
require.NoError(err)
|
||||
require.Equal(1, numCatUpdated)
|
||||
|
||||
// Set up some secrets
|
||||
cSecretProto := mustStruct(map[string]interface{}{
|
||||
scopeWrapper, err := dbKmsCache.GetWrapper(ctx, cat.GetScopeId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(err)
|
||||
cat.Secrets = mustStruct(map[string]interface{}{
|
||||
"one": "two",
|
||||
})
|
||||
cSecret, err := newHostCatalogSecret(ctx, cat.GetPublicId(), cSecretProto)
|
||||
require.NoError(err)
|
||||
scopeWrapper, err := dbKmsCache.GetWrapper(ctx, cat.GetScopeId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(cat.hmacSecrets(ctx, scopeWrapper))
|
||||
cSecret, err := newHostCatalogSecret(ctx, cat.GetPublicId(), cat.Secrets)
|
||||
require.NoError(err)
|
||||
require.NoError(cSecret.encrypt(ctx, scopeWrapper))
|
||||
cSecretQ, cSecretV := cSecret.upsertQuery()
|
||||
@@ -1104,6 +1122,14 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
require.NoError(err)
|
||||
require.Equal(1, secretsUpdated)
|
||||
|
||||
// Set some (default) attributes on our test catalog and update SecretsHmac at the same time
|
||||
cat.Attributes = mustMarshal(map[string]interface{}{
|
||||
"foo": "bar",
|
||||
})
|
||||
numCatUpdated, err := dbRW.Update(ctx, cat, []string{"attributes", "SecretsHmac"}, []string{})
|
||||
require.NoError(err)
|
||||
require.Equal(1, numCatUpdated)
|
||||
|
||||
t.Cleanup(func() {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
|
||||
@@ -55,9 +55,14 @@ type HostCatalog struct {
|
||||
// version allows optimistic locking of the resource
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Version uint32 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
|
||||
// secrets_hmac is a sha256-hmac of the unencrypted secrets that is returned
|
||||
// from the API for read. It is recalculated everytime the raw secrets are
|
||||
// updated.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
SecretsHmac []byte `protobuf:"bytes,9,opt,name=secrets_hmac,json=secretsHmac,proto3" json:"secrets_hmac,omitempty" gorm:"default:null"`
|
||||
// attributes is a jsonb formatted field.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
Attributes []byte `protobuf:"bytes,9,opt,name=attributes,proto3" json:"attributes,omitempty" gorm:"not_null"`
|
||||
Attributes []byte `protobuf:"bytes,10,opt,name=attributes,proto3" json:"attributes,omitempty" gorm:"not_null"`
|
||||
}
|
||||
|
||||
func (x *HostCatalog) Reset() {
|
||||
@@ -148,6 +153,13 @@ func (x *HostCatalog) GetVersion() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HostCatalog) GetSecretsHmac() []byte {
|
||||
if x != nil {
|
||||
return x.SecretsHmac
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *HostCatalog) GetAttributes() []byte {
|
||||
if x != nil {
|
||||
return x.Attributes
|
||||
@@ -644,7 +656,7 @@ var file_controller_storage_host_plugin_store_v1_host_proto_rawDesc = []byte{
|
||||
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, 0x9e, 0x03, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
|
||||
0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc1, 0x03, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f,
|
||||
@@ -668,106 +680,108 @@ var file_controller_storage_host_plugin_store_v1_host_proto_rawDesc = []byte{
|
||||
0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x64, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xb6, 0x05, 0x0a, 0x07, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 0x73, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x0b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x48, 0x6d, 0x61, 0x63, 0x12, 0x1e, 0x0a, 0x0a,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xb6, 0x05, 0x0a,
|
||||
0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 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, 0x03, 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, 0x03,
|
||||
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, 0x50, 0x0a, 0x0e,
|
||||
0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04,
|
||||
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, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x6e, 0x65, 0x65, 0x64, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x08, 0x6e, 0x65, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x24, 0x0a, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x06, 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, 0x07, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67,
|
||||
0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x5e, 0x0a, 0x13,
|
||||
0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x42, 0x2d, 0xc2, 0xdd, 0x29, 0x29, 0x0a,
|
||||
0x12, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x73, 0x12, 0x13, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x65,
|
||||
0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x12, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72,
|
||||
0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x15,
|
||||
0x73, 0x79, 0x6e, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65,
|
||||
0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x42, 0x30, 0xc2, 0xdd, 0x29,
|
||||
0x2c, 0x0a, 0x13, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53,
|
||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x15, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x52, 0x13, 0x73,
|
||||
0x79, 0x6e, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e,
|
||||
0x64, 0x73, 0x22, 0x98, 0x02, 0x0a, 0x11, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
0x50, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x18, 0x04, 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, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x65, 0x64, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x65, 0x65, 0x64, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x24,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 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, 0x07, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
|
||||
0x5e, 0x0a, 0x13, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x42, 0x2d, 0xc2, 0xdd,
|
||||
0x29, 0x29, 0x0a, 0x12, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x13, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65,
|
||||
0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x12, 0x70, 0x72, 0x65,
|
||||
0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12,
|
||||
0x64, 0x0a, 0x15, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
|
||||
0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x42, 0x30,
|
||||
0xc2, 0xdd, 0x29, 0x2c, 0x0a, 0x13, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
||||
0x61, 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x15, 0x73, 0x79, 0x6e, 0x63, 0x5f,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73,
|
||||
0x52, 0x13, 0x73, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65,
|
||||
0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x98, 0x02, 0x0a, 0x11, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 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, 0x03, 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, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x63, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x08, 0x63, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64,
|
||||
0x22, 0x8d, 0x03, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75,
|
||||
0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x18, 0x04, 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, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x74, 0x5f,
|
||||
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x74,
|
||||
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x22, 0x8d, 0x03,
|
||||
0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x18, 0x03, 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, 0x04, 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, 0x12,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a,
|
||||
0x0c, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x5e, 0x0a,
|
||||
0x0d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17,
|
||||
0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x74, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x42, 0x40, 0x5a,
|
||||
0x3e, 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, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x70, 0x6c, 0x75,
|
||||
0x67, 0x69, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x21, 0x0a, 0x0c, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
|
||||
0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73,
|
||||
0x22, 0x5e, 0x0a, 0x0d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65,
|
||||
0x72, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65,
|
||||
0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x65, 0x74, 0x49,
|
||||
0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64,
|
||||
0x42, 0x40, 0x5a, 0x3e, 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, 0x68, 0x6f, 0x73, 0x74, 0x2f,
|
||||
0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/mr-tron/base58"
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
@@ -81,10 +82,12 @@ func HmacSha256(ctx context.Context, data []byte, cipher wrapping.Wrapper, salt,
|
||||
hmac := mac.Sum(nil)
|
||||
|
||||
var hmacString string
|
||||
switch opts.withBase64Encoding {
|
||||
case true:
|
||||
switch {
|
||||
case opts.withBase64Encoding:
|
||||
hmacString = base64.RawURLEncoding.EncodeToString(hmac)
|
||||
case false:
|
||||
case opts.withBase58Encoding:
|
||||
hmacString = base58.Encode(hmac)
|
||||
default:
|
||||
hmacString = string(hmac)
|
||||
}
|
||||
if opts.withPrefix != "" {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/blake2b"
|
||||
@@ -65,12 +66,19 @@ func Test_HmacSha256(t *testing.T) {
|
||||
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:")),
|
||||
},
|
||||
{
|
||||
name: "blake2b-with-prefix-with-bas64",
|
||||
name: "blake2b-with-prefix-with-base64",
|
||||
data: []byte("test"),
|
||||
wrapper: testWrapper,
|
||||
opts: []Option{WithPrefix("prefix:"), WithBase64Encoding()},
|
||||
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:"), WithBase64Encoding()),
|
||||
},
|
||||
{
|
||||
name: "blake2b-with-prefix-with-base58",
|
||||
data: []byte("test"),
|
||||
wrapper: testWrapper,
|
||||
opts: []Option{WithPrefix("prefix:"), WithBase58Encoding()},
|
||||
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:"), WithBase58Encoding()),
|
||||
},
|
||||
{
|
||||
name: "with-prk",
|
||||
data: []byte("test"),
|
||||
@@ -155,10 +163,12 @@ func testHmac(t *testing.T, key, data []byte, opt ...Option) string {
|
||||
var hmacString string
|
||||
opts, err := getOpts(opt...)
|
||||
require.NoError(err)
|
||||
switch opts.withBase64Encoding {
|
||||
case true:
|
||||
switch {
|
||||
case opts.withBase64Encoding:
|
||||
hmacString = base64.RawURLEncoding.EncodeToString(hmac)
|
||||
case false:
|
||||
case opts.withBase58Encoding:
|
||||
hmacString = base58.Encode(hmac)
|
||||
default:
|
||||
hmacString = string(hmac)
|
||||
}
|
||||
if opts.withPrefix != "" {
|
||||
|
||||
@@ -22,6 +22,7 @@ type options struct {
|
||||
withPrk []byte
|
||||
withEd25519 bool
|
||||
withBase64Encoding bool
|
||||
withBase58Encoding bool
|
||||
}
|
||||
|
||||
func getDefaultOptions() *options {
|
||||
@@ -61,3 +62,11 @@ func WithBase64Encoding() Option {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBase58Encoding allows an optional request to base58 encode the data returned
|
||||
func WithBase58Encoding() Option {
|
||||
return func(o *options) error {
|
||||
o.withBase58Encoding = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -42,4 +42,12 @@ func Test_GetOpts(t *testing.T) {
|
||||
testOpts.withBase64Encoding = true
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
t.Run("WithBase58Encoding", func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
opts, err := getOpts(WithBase58Encoding())
|
||||
require.NoError(err)
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withBase58Encoding = true
|
||||
assert.Equal(opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -53,6 +53,9 @@ message HostCatalog {
|
||||
// Secrets specific to the catalog type. These are never output.
|
||||
google.protobuf.Struct secrets = 110 [(custom_options.v1.generate_sdk_option) = true];
|
||||
|
||||
// Output only. The HMAC of the last secrets supplied via the API, if any.
|
||||
string secrets_hmac = 120;
|
||||
|
||||
// Output only. The available actions on this resource for this user.
|
||||
repeated string authorized_actions = 300 [json_name="authorized_actions"];
|
||||
|
||||
|
||||
@@ -42,9 +42,15 @@ message HostCatalog {
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
uint32 version = 8;
|
||||
|
||||
// secrets_hmac is a sha256-hmac of the unencrypted secrets that is returned
|
||||
// from the API for read. It is recalculated everytime the raw secrets are
|
||||
// updated.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
bytes secrets_hmac = 9;
|
||||
|
||||
// attributes is a jsonb formatted field.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
bytes attributes = 9;
|
||||
bytes attributes = 10;
|
||||
}
|
||||
|
||||
message HostSet {
|
||||
@@ -184,4 +190,4 @@ message HostSetMember {
|
||||
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string catalog_id = 3;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/hashicorp/boundary/internal/host"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin"
|
||||
pluginstore "github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/perms"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/types/subtypes"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins"
|
||||
"github.com/mr-tron/base58"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
@@ -33,7 +35,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
maskManager handlers.MaskManager
|
||||
staticMaskManager handlers.MaskManager
|
||||
pluginMaskManager handlers.MaskManager
|
||||
|
||||
// IdActions contains the set of actions that can be performed on
|
||||
// individual resources
|
||||
@@ -67,7 +70,10 @@ var (
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
if maskManager, err = handlers.NewMaskManager(handlers.MaskDestination{&store.HostCatalog{}}, handlers.MaskSource{&pb.HostCatalog{}}); err != nil {
|
||||
if staticMaskManager, err = handlers.NewMaskManager(handlers.MaskDestination{&store.HostCatalog{}}, handlers.MaskSource{&pb.HostCatalog{}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if pluginMaskManager, err = handlers.NewMaskManager(handlers.MaskDestination{&pluginstore.HostCatalog{}}, handlers.MaskSource{&pb.HostCatalog{}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -521,7 +527,7 @@ func (s Service) updateStaticInRepo(ctx context.Context, projId, id string, mask
|
||||
}
|
||||
version := item.GetVersion()
|
||||
h.PublicId = id
|
||||
dbMask := maskManager.Translate(mask)
|
||||
dbMask := staticMaskManager.Translate(mask)
|
||||
if len(dbMask) == 0 {
|
||||
return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
|
||||
}
|
||||
@@ -547,7 +553,7 @@ func (s Service) updatePluginInRepo(ctx context.Context, projId, id string, mask
|
||||
}
|
||||
version := item.GetVersion()
|
||||
h.PublicId = id
|
||||
dbMask := maskManager.Translate(mask, "attributes", "secrets")
|
||||
dbMask := pluginMaskManager.Translate(mask, "attributes", "secrets")
|
||||
if len(dbMask) == 0 {
|
||||
return nil, nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."})
|
||||
}
|
||||
@@ -693,12 +699,6 @@ func toProto(ctx context.Context, in host.Catalog, opt ...handlers.Option) (*pb.
|
||||
if outputFields.Has(globals.ScopeIdField) {
|
||||
out.ScopeId = in.GetScopeId()
|
||||
}
|
||||
if outputFields.Has(globals.PluginIdField) {
|
||||
switch hc := in.(type) {
|
||||
case *plugin.HostCatalog:
|
||||
out.PluginId = hc.GetPluginId()
|
||||
}
|
||||
}
|
||||
if outputFields.Has(globals.TypeField) {
|
||||
switch in.(type) {
|
||||
case *static.HostCatalog:
|
||||
@@ -734,9 +734,15 @@ func toProto(ctx context.Context, in host.Catalog, opt ...handlers.Option) (*pb.
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
out.AuthorizedCollectionActions = opts.WithAuthorizedCollectionActions
|
||||
}
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
switch h := in.(type) {
|
||||
case *plugin.HostCatalog:
|
||||
switch h := in.(type) {
|
||||
case *plugin.HostCatalog:
|
||||
if outputFields.Has(globals.PluginIdField) {
|
||||
out.PluginId = h.GetPluginId()
|
||||
}
|
||||
if outputFields.Has(globals.SecretsHmacField) {
|
||||
out.SecretsHmac = base58.Encode(h.GetSecretsHmac())
|
||||
}
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
attrs := &structpb.Struct{}
|
||||
err := proto.Unmarshal(h.Attributes, attrs)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins"
|
||||
scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/mr-tron/base58"
|
||||
"google.golang.org/genproto/protobuf/field_mask"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -183,7 +184,7 @@ func TestGet_Plugin(t *testing.T) {
|
||||
}
|
||||
name := "test"
|
||||
plg := host.TestPlugin(t, conn, name)
|
||||
hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
|
||||
hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId(), plugin.WithSecretsHmac([]byte("foobar")))
|
||||
|
||||
toMerge := &pbs.GetHostCatalogRequest{
|
||||
Id: hc.GetPublicId(),
|
||||
@@ -208,6 +209,7 @@ func TestGet_Plugin(t *testing.T) {
|
||||
Type: plugin.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions[plugin.Subtype],
|
||||
SecretsHmac: base58.Encode([]byte("foobar")),
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
|
||||
@@ -59,6 +59,8 @@ type HostCatalog struct {
|
||||
Attributes *structpb.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"`
|
||||
// Secrets specific to the catalog type. These are never output.
|
||||
Secrets *structpb.Struct `protobuf:"bytes,110,opt,name=secrets,proto3" json:"secrets,omitempty"`
|
||||
// Output only. The HMAC of the last secrets supplied via the API, if any.
|
||||
SecretsHmac string `protobuf:"bytes,120,opt,name=secrets_hmac,json=secretsHmac,proto3" json:"secrets_hmac,omitempty"`
|
||||
// Output only. The available actions on this resource for this user.
|
||||
AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"`
|
||||
// Output only. The authorized actions for the scope's collections.
|
||||
@@ -188,6 +190,13 @@ func (x *HostCatalog) GetSecrets() *structpb.Struct {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *HostCatalog) GetSecretsHmac() string {
|
||||
if x != nil {
|
||||
return x.SecretsHmac
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HostCatalog) GetAuthorizedActions() []string {
|
||||
if x != nil {
|
||||
return x.AuthorizedActions
|
||||
@@ -226,7 +235,7 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [
|
||||
0x69, 0x6e, 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, 0xfa, 0x07, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9d, 0x08, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 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,
|
||||
@@ -270,33 +279,35 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x6e, 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, 0x07, 0x73, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 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, 0x12, 0x9d, 0x01, 0x0a, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56,
|
||||
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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64,
|
||||
0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
|
||||
0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
|
||||
0x72, 0x65, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x5f,
|
||||
0x68, 0x6d, 0x61, 0x63, 0x18, 0x78, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x63, 0x72,
|
||||
0x65, 0x74, 0x73, 0x48, 0x6d, 0x61, 0x63, 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, 0x12, 0x9d, 0x01, 0x0a, 0x1d, 0x61, 0x75, 0x74,
|
||||
0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x56, 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, 0x68, 0x6f, 0x73,
|
||||
0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
|
||||
0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x42, 0x5a, 0x5a, 0x58, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x3b, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f,
|
||||
0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68,
|
||||
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30,
|
||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x42, 0x5a, 0x5a, 0x58, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x73, 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
Reference in new issue
Block a user