mirror of https://github.com/status-im/consul.git
Merge pull request #7900 from hashicorp/dnephin/add-linter-staticcheck-2
intentions: fix a bug in Intention.SetHash
This commit is contained in:
commit
08f1ed16b4
|
@ -86,7 +86,7 @@ func (s *Intention) prepareApplyCreate(ident structs.ACLIdentity, authz acl.Auth
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we set the hash prior to raft application
|
// make sure we set the hash prior to raft application
|
||||||
args.Intention.SetHash(true)
|
args.Intention.SetHash()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ func (s *Intention) prepareApplyUpdate(ident structs.ACLIdentity, authz acl.Auth
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we set the hash prior to raft application
|
// make sure we set the hash prior to raft application
|
||||||
args.Intention.SetHash(true)
|
args.Intention.SetHash()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1996,8 +1996,6 @@ func TestDecodeCatalogRegister(t *testing.T) {
|
||||||
// DestinationName string
|
// DestinationName string
|
||||||
// SourceType structs.IntentionSourceType
|
// SourceType structs.IntentionSourceType
|
||||||
// Action structs.IntentionAction
|
// Action structs.IntentionAction
|
||||||
// DefaultAddr string
|
|
||||||
// DefaultPort int
|
|
||||||
// Meta map[string]string
|
// Meta map[string]string
|
||||||
// Precedence int
|
// Precedence int
|
||||||
// CreatedAt time.Time mapstructure:'-'
|
// CreatedAt time.Time mapstructure:'-'
|
||||||
|
|
|
@ -55,10 +55,12 @@ type Intention struct {
|
||||||
// Action is whether this is an allowlist or denylist intention.
|
// Action is whether this is an allowlist or denylist intention.
|
||||||
Action IntentionAction
|
Action IntentionAction
|
||||||
|
|
||||||
// DefaultAddr, DefaultPort of the local listening proxy (if any) to
|
// DefaultAddr is not used.
|
||||||
// make this connection.
|
// Deprecated: DefaultAddr is not used and may be removed in a future version.
|
||||||
DefaultAddr string
|
DefaultAddr string `bexpr:"-" codec:",omitempty"`
|
||||||
DefaultPort int
|
// DefaultPort is not used.
|
||||||
|
// Deprecated: DefaultPort is not used and may be removed in a future version.
|
||||||
|
DefaultPort int `bexpr:"-" codec:",omitempty"`
|
||||||
|
|
||||||
// Meta is arbitrary metadata associated with the intention. This is
|
// Meta is arbitrary metadata associated with the intention. This is
|
||||||
// opaque to Consul but is served in API responses.
|
// opaque to Consul but is served in API responses.
|
||||||
|
@ -103,22 +105,18 @@ func (t *Intention) UnmarshalJSON(data []byte) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: staticcheck // should be fixed in https://github.com/hashicorp/consul/pull/7900
|
// SetHash calculates Intention.Hash from any mutable "content" fields.
|
||||||
func (x *Intention) SetHash(force bool) []byte {
|
//
|
||||||
if force || x.Hash == nil {
|
// The Hash is primarily used for replication to determine if a token
|
||||||
|
// has changed and should be updated locally.
|
||||||
|
//
|
||||||
|
// TODO: move to agent/consul where it is called
|
||||||
|
func (x *Intention) SetHash() {
|
||||||
hash, err := blake2b.New256(nil)
|
hash, err := blake2b.New256(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any non-immutable "content" fields should be involved with the
|
|
||||||
// overall hash. The IDs are immutable which is why they aren't here.
|
|
||||||
// The raft indices are metadata similar to the hash which is why they
|
|
||||||
// aren't incorporated. CreateTime is similarly immutable
|
|
||||||
//
|
|
||||||
// The Hash is really only used for replication to determine if a token
|
|
||||||
// has changed and should be updated locally.
|
|
||||||
|
|
||||||
// Write all the user set fields
|
// Write all the user set fields
|
||||||
hash.Write([]byte(x.ID))
|
hash.Write([]byte(x.ID))
|
||||||
hash.Write([]byte(x.Description))
|
hash.Write([]byte(x.Description))
|
||||||
|
@ -128,17 +126,18 @@ func (x *Intention) SetHash(force bool) []byte {
|
||||||
hash.Write([]byte(x.DestinationName))
|
hash.Write([]byte(x.DestinationName))
|
||||||
hash.Write([]byte(x.SourceType))
|
hash.Write([]byte(x.SourceType))
|
||||||
hash.Write([]byte(x.Action))
|
hash.Write([]byte(x.Action))
|
||||||
hash.Write([]byte(x.DefaultAddr))
|
// hash.Write can not return an error, so the only way for binary.Write to
|
||||||
binary.Write(hash, binary.LittleEndian, x.DefaultPort)
|
// error is to pass it data with an invalid data type. Doing so would be a
|
||||||
binary.Write(hash, binary.LittleEndian, x.Precedence)
|
// programming error, so panic in that case.
|
||||||
|
if err := binary.Write(hash, binary.LittleEndian, uint64(x.Precedence)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
// hashing the metadata
|
// sort keys to ensure hash stability when meta is stored later
|
||||||
var keys []string
|
var keys []string
|
||||||
for k := range x.Meta {
|
for k := range x.Meta {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep them sorted to ensure hash stability
|
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
|
@ -146,12 +145,7 @@ func (x *Intention) SetHash(force bool) []byte {
|
||||||
hash.Write([]byte(x.Meta[k]))
|
hash.Write([]byte(x.Meta[k]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the hash
|
x.Hash = hash.Sum(nil)
|
||||||
hashVal := hash.Sum(nil)
|
|
||||||
|
|
||||||
x.Hash = hashVal
|
|
||||||
}
|
|
||||||
return x.Hash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate returns an error if the intention is invalid for inserting
|
// Validate returns an error if the intention is invalid for inserting
|
||||||
|
@ -337,9 +331,9 @@ func (x *Intention) String() string {
|
||||||
|
|
||||||
// EstimateSize returns an estimate (in bytes) of the size of this structure when encoded.
|
// EstimateSize returns an estimate (in bytes) of the size of this structure when encoded.
|
||||||
func (x *Intention) EstimateSize() int {
|
func (x *Intention) EstimateSize() int {
|
||||||
// 60 = 36 (uuid) + 16 (RaftIndex) + 4 (Precedence) + 4 (DefaultPort)
|
// 56 = 36 (uuid) + 16 (RaftIndex) + 4 (Precedence)
|
||||||
size := 60 + len(x.Description) + len(x.SourceNS) + len(x.SourceName) + len(x.DestinationNS) +
|
size := 56 + len(x.Description) + len(x.SourceNS) + len(x.SourceName) + len(x.DestinationNS) +
|
||||||
len(x.DestinationName) + len(x.SourceType) + len(x.Action) + len(x.DefaultAddr)
|
len(x.DestinationName) + len(x.SourceType) + len(x.Action)
|
||||||
|
|
||||||
for k, v := range x.Meta {
|
for k, v := range x.Meta {
|
||||||
size += len(k) + len(v)
|
size += len(k) + len(v)
|
||||||
|
|
|
@ -334,3 +334,28 @@ func TestIntentionPrecedenceSorter(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntention_SetHash(t *testing.T) {
|
||||||
|
i := Intention{
|
||||||
|
ID: "the-id",
|
||||||
|
Description: "the-description",
|
||||||
|
SourceNS: "source-ns",
|
||||||
|
SourceName: "source-name",
|
||||||
|
DestinationNS: "dest-ns",
|
||||||
|
DestinationName: "dest-name",
|
||||||
|
SourceType: "source-type",
|
||||||
|
Action: "action",
|
||||||
|
Precedence: 123,
|
||||||
|
Meta: map[string]string{
|
||||||
|
"meta1": "one",
|
||||||
|
"meta2": "two",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
i.SetHash()
|
||||||
|
expected := []byte{
|
||||||
|
0x20, 0x89, 0x55, 0xdb, 0x69, 0x34, 0xce, 0x89, 0xd8, 0xb9, 0x2e, 0x3a,
|
||||||
|
0x85, 0xb6, 0xea, 0x43, 0xb2, 0x23, 0x16, 0x93, 0x94, 0x13, 0x2a, 0xe4,
|
||||||
|
0x81, 0xfe, 0xe, 0x34, 0x91, 0x99, 0xe9, 0x8d,
|
||||||
|
}
|
||||||
|
require.Equal(t, expected, i.Hash)
|
||||||
|
}
|
||||||
|
|
|
@ -566,16 +566,6 @@ var expectedFieldConfigIntention bexpr.FieldConfigurations = bexpr.FieldConfigur
|
||||||
CoerceFn: bexpr.CoerceString,
|
CoerceFn: bexpr.CoerceString,
|
||||||
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
|
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
|
||||||
},
|
},
|
||||||
"DefaultAddr": &bexpr.FieldConfiguration{
|
|
||||||
StructFieldName: "DefaultAddr",
|
|
||||||
CoerceFn: bexpr.CoerceString,
|
|
||||||
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches},
|
|
||||||
},
|
|
||||||
"DefaultPort": &bexpr.FieldConfiguration{
|
|
||||||
StructFieldName: "DefaultPort",
|
|
||||||
CoerceFn: bexpr.CoerceInt,
|
|
||||||
SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual},
|
|
||||||
},
|
|
||||||
"Precedence": &bexpr.FieldConfiguration{
|
"Precedence": &bexpr.FieldConfiguration{
|
||||||
StructFieldName: "Precedence",
|
StructFieldName: "Precedence",
|
||||||
CoerceFn: bexpr.CoerceInt,
|
CoerceFn: bexpr.CoerceInt,
|
||||||
|
|
|
@ -36,10 +36,12 @@ type Intention struct {
|
||||||
// Action is whether this is an allowlist or denylist intention.
|
// Action is whether this is an allowlist or denylist intention.
|
||||||
Action IntentionAction
|
Action IntentionAction
|
||||||
|
|
||||||
// DefaultAddr, DefaultPort of the local listening proxy (if any) to
|
// DefaultAddr is not used.
|
||||||
// make this connection.
|
// Deprecated: DefaultAddr is not used and may be removed in a future version.
|
||||||
DefaultAddr string
|
DefaultAddr string `json:",omitempty"`
|
||||||
DefaultPort int
|
// DefaultPort is not used.
|
||||||
|
// Deprecated: DefaultPort is not used and may be removed in a future version.
|
||||||
|
DefaultPort int `json:",omitempty"`
|
||||||
|
|
||||||
// Meta is arbitrary metadata associated with the intention. This is
|
// Meta is arbitrary metadata associated with the intention. This is
|
||||||
// opaque to Consul but is served in API responses.
|
// opaque to Consul but is served in API responses.
|
||||||
|
|
|
@ -14,11 +14,6 @@ export default Model.extend({
|
||||||
Precedence: attr('number'),
|
Precedence: attr('number'),
|
||||||
SourceType: attr('string', { defaultValue: 'consul' }),
|
SourceType: attr('string', { defaultValue: 'consul' }),
|
||||||
Action: attr('string', { defaultValue: 'deny' }),
|
Action: attr('string', { defaultValue: 'deny' }),
|
||||||
// These are in the API response but up until now
|
|
||||||
// aren't used for anything
|
|
||||||
DefaultAddr: attr('string'),
|
|
||||||
DefaultPort: attr('number'),
|
|
||||||
//
|
|
||||||
Meta: attr(),
|
Meta: attr(),
|
||||||
SyncTime: attr('number'),
|
SyncTime: attr('number'),
|
||||||
Datacenter: attr('string'),
|
Datacenter: attr('string'),
|
||||||
|
|
|
@ -145,8 +145,6 @@ $ curl \
|
||||||
"DestinationName": "db",
|
"DestinationName": "db",
|
||||||
"SourceType": "consul",
|
"SourceType": "consul",
|
||||||
"Action": "allow",
|
"Action": "allow",
|
||||||
"DefaultAddr": "",
|
|
||||||
"DefaultPort": 0,
|
|
||||||
"Meta": {},
|
"Meta": {},
|
||||||
"Precedence": 9,
|
"Precedence": 9,
|
||||||
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
||||||
|
@ -208,8 +206,6 @@ $ curl \
|
||||||
"DestinationName": "db",
|
"DestinationName": "db",
|
||||||
"SourceType": "consul",
|
"SourceType": "consul",
|
||||||
"Action": "allow",
|
"Action": "allow",
|
||||||
"DefaultAddr": "",
|
|
||||||
"DefaultPort": 0,
|
|
||||||
"Meta": {},
|
"Meta": {},
|
||||||
"Precedence": 9,
|
"Precedence": 9,
|
||||||
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
||||||
|
@ -228,8 +224,6 @@ the following selectors and filter operations being supported:
|
||||||
| Selector | Supported Operations |
|
| Selector | Supported Operations |
|
||||||
| ----------------- | -------------------------------------------------- |
|
| ----------------- | -------------------------------------------------- |
|
||||||
| `Action` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
| `Action` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
||||||
| `DefaultAddr` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
|
||||||
| `DefaultPort` | Equal, Not Equal |
|
|
||||||
| `Description` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
| `Description` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
||||||
| `DestinationNS` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
| `DestinationNS` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
||||||
| `DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
| `DestinationName` | Equal, Not Equal, In, Not In, Matches, Not Matches |
|
||||||
|
@ -450,8 +444,6 @@ $ curl \
|
||||||
"DestinationName": "db",
|
"DestinationName": "db",
|
||||||
"SourceType": "consul",
|
"SourceType": "consul",
|
||||||
"Action": "deny",
|
"Action": "deny",
|
||||||
"DefaultAddr": "",
|
|
||||||
"DefaultPort": 0,
|
|
||||||
"Meta": {},
|
"Meta": {},
|
||||||
"CreatedAt": "2018-05-21T16:41:33.296693825Z",
|
"CreatedAt": "2018-05-21T16:41:33.296693825Z",
|
||||||
"UpdatedAt": "2018-05-21T16:41:33.296694288Z",
|
"UpdatedAt": "2018-05-21T16:41:33.296694288Z",
|
||||||
|
@ -467,8 +459,6 @@ $ curl \
|
||||||
"DestinationName": "*",
|
"DestinationName": "*",
|
||||||
"SourceType": "consul",
|
"SourceType": "consul",
|
||||||
"Action": "allow",
|
"Action": "allow",
|
||||||
"DefaultAddr": "",
|
|
||||||
"DefaultPort": 0,
|
|
||||||
"Meta": {},
|
"Meta": {},
|
||||||
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
"CreatedAt": "2018-05-21T16:41:27.977155457Z",
|
||||||
"UpdatedAt": "2018-05-21T16:41:27.977157724Z",
|
"UpdatedAt": "2018-05-21T16:41:27.977157724Z",
|
||||||
|
|
Loading…
Reference in New Issue