github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/message/authorization.go (about)

     1  package message
     2  
     3  import (
     4  	"github.com/onflow/flow-go/model/flow"
     5  	"github.com/onflow/flow-go/model/libp2p/message"
     6  	"github.com/onflow/flow-go/model/messages"
     7  	"github.com/onflow/flow-go/network/channels"
     8  )
     9  
    10  type ChannelAuthConfig struct {
    11  	// AuthorizedRoles list of roles authorized to send this message on the channel.
    12  	AuthorizedRoles flow.RoleList
    13  
    14  	// AllowedProtocols list of protocols the message is allowed to be sent on. Currently AllowedProtocols is expected to have
    15  	// exactly one element in the list. This is due to the fact that currently there are no messages that are used with both protocols aside from TestMessage.
    16  	AllowedProtocols Protocols
    17  }
    18  
    19  var authorizationConfigs map[string]MsgAuthConfig
    20  
    21  // MsgAuthConfig contains authorization information for a specific flow message. The authorization
    22  // is represented as a map from network channel -> list of all roles allowed to send the message on
    23  // the channel.
    24  type MsgAuthConfig struct {
    25  	// Name is the string representation of the message type.
    26  	Name string
    27  	// Type is a func that returns a new instance of message type.
    28  	Type func() interface{}
    29  	// Config is the mapping of network channel to list of authorized flow roles.
    30  	Config map[channels.Channel]ChannelAuthConfig
    31  }
    32  
    33  // EnsureAuthorized checks if the specified role is authorized to send the message on the provided channel and
    34  // asserts that the message is authorized to be sent on the channel.
    35  // Expected error returns during normal operations:
    36  //   - ErrUnauthorizedMessageOnChannel: the channel is not included in the message's list of authorized channels
    37  //   - ErrUnauthorizedRole: the role is not included in the message's list of authorized roles for the provided channel
    38  //   - ErrUnauthorizedUnicastOnChannel: the message is not authorized to be sent via unicast protocol.
    39  //   - ErrUnauthorizedPublishOnChannel: the message is not authorized to be sent via publish protocol.
    40  func (m MsgAuthConfig) EnsureAuthorized(role flow.Role, channel channels.Channel, protocol ProtocolType) error {
    41  	authConfig, ok := m.Config[channel]
    42  	if !ok {
    43  		return ErrUnauthorizedMessageOnChannel
    44  	}
    45  
    46  	if !authConfig.AuthorizedRoles.Contains(role) {
    47  		return ErrUnauthorizedRole
    48  	}
    49  
    50  	if !authConfig.AllowedProtocols.Contains(protocol) {
    51  		return NewUnauthorizedProtocolError(protocol)
    52  	}
    53  
    54  	return nil
    55  }
    56  
    57  func initializeMessageAuthConfigsMap() {
    58  	authorizationConfigs = make(map[string]MsgAuthConfig)
    59  
    60  	// consensus
    61  	authorizationConfigs[BlockProposal] = MsgAuthConfig{
    62  		Name: BlockProposal,
    63  		Type: func() interface{} {
    64  			return new(messages.BlockProposal)
    65  		},
    66  		Config: map[channels.Channel]ChannelAuthConfig{
    67  			channels.ConsensusCommittee: {
    68  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
    69  				AllowedProtocols: Protocols{ProtocolTypePubSub},
    70  			},
    71  			channels.PushBlocks: {
    72  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
    73  				AllowedProtocols: Protocols{ProtocolTypePubSub},
    74  			}, // channel alias ReceiveBlocks = PushBlocks
    75  		},
    76  	}
    77  	authorizationConfigs[BlockVote] = MsgAuthConfig{
    78  		Name: BlockVote,
    79  		Type: func() interface{} {
    80  			return new(messages.BlockVote)
    81  		},
    82  		Config: map[channels.Channel]ChannelAuthConfig{
    83  			channels.ConsensusCommittee: {
    84  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
    85  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
    86  			},
    87  		},
    88  	}
    89  	authorizationConfigs[TimeoutObject] = MsgAuthConfig{
    90  		Name: TimeoutObject,
    91  		Type: func() interface{} {
    92  			return new(messages.TimeoutObject)
    93  		},
    94  		Config: map[channels.Channel]ChannelAuthConfig{
    95  			channels.ConsensusCommittee: {
    96  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
    97  				AllowedProtocols: Protocols{ProtocolTypePubSub},
    98  			},
    99  		},
   100  	}
   101  
   102  	// protocol state sync
   103  	authorizationConfigs[SyncRequest] = MsgAuthConfig{
   104  		Name: SyncRequest,
   105  		Type: func() interface{} {
   106  			return new(messages.SyncRequest)
   107  		},
   108  		Config: map[channels.Channel]ChannelAuthConfig{
   109  			channels.SyncCommittee: {
   110  				AuthorizedRoles:  flow.Roles(),
   111  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   112  			},
   113  			channels.SyncClusterPrefix: {
   114  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   115  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   116  			},
   117  		},
   118  	}
   119  	authorizationConfigs[SyncResponse] = MsgAuthConfig{
   120  		Name: SyncResponse,
   121  		Type: func() interface{} {
   122  			return new(messages.SyncResponse)
   123  		},
   124  		Config: map[channels.Channel]ChannelAuthConfig{
   125  			channels.SyncCommittee: {
   126  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
   127  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   128  			},
   129  			channels.SyncClusterPrefix: {
   130  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   131  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   132  			},
   133  		},
   134  	}
   135  	authorizationConfigs[RangeRequest] = MsgAuthConfig{
   136  		Name: RangeRequest,
   137  		Type: func() interface{} {
   138  			return new(messages.RangeRequest)
   139  		},
   140  		Config: map[channels.Channel]ChannelAuthConfig{
   141  			channels.SyncCommittee: {
   142  				AuthorizedRoles:  flow.Roles(),
   143  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   144  			},
   145  			channels.SyncClusterPrefix: {
   146  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   147  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   148  			},
   149  		},
   150  	}
   151  	authorizationConfigs[BatchRequest] = MsgAuthConfig{
   152  		Name: BatchRequest,
   153  		Type: func() interface{} {
   154  			return new(messages.BatchRequest)
   155  		},
   156  		Config: map[channels.Channel]ChannelAuthConfig{
   157  			channels.SyncCommittee: {
   158  				AuthorizedRoles:  flow.Roles(),
   159  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   160  			},
   161  			channels.SyncClusterPrefix: {
   162  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   163  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   164  			},
   165  		},
   166  	}
   167  	authorizationConfigs[BlockResponse] = MsgAuthConfig{
   168  		Name: BlockResponse,
   169  		Type: func() interface{} {
   170  			return new(messages.BlockResponse)
   171  		},
   172  		Config: map[channels.Channel]ChannelAuthConfig{
   173  			channels.SyncCommittee: {
   174  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
   175  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   176  			},
   177  		},
   178  	}
   179  
   180  	// cluster consensus
   181  	authorizationConfigs[ClusterBlockProposal] = MsgAuthConfig{
   182  		Name: ClusterBlockProposal,
   183  		Type: func() interface{} {
   184  			return new(messages.ClusterBlockProposal)
   185  		},
   186  		Config: map[channels.Channel]ChannelAuthConfig{
   187  			channels.ConsensusClusterPrefix: {
   188  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   189  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   190  			},
   191  		},
   192  	}
   193  	authorizationConfigs[ClusterBlockVote] = MsgAuthConfig{
   194  		Name: ClusterBlockVote,
   195  		Type: func() interface{} {
   196  			return new(messages.ClusterBlockVote)
   197  		},
   198  		Config: map[channels.Channel]ChannelAuthConfig{
   199  			channels.ConsensusClusterPrefix: {
   200  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   201  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   202  			},
   203  		},
   204  	}
   205  	authorizationConfigs[ClusterTimeoutObject] = MsgAuthConfig{
   206  		Name: ClusterTimeoutObject,
   207  		Type: func() interface{} {
   208  			return new(messages.ClusterTimeoutObject)
   209  		},
   210  		Config: map[channels.Channel]ChannelAuthConfig{
   211  			channels.ConsensusClusterPrefix: {
   212  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   213  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   214  			},
   215  		},
   216  	}
   217  	authorizationConfigs[ClusterBlockResponse] = MsgAuthConfig{
   218  		Name: ClusterBlockResponse,
   219  		Type: func() interface{} {
   220  			return new(messages.ClusterBlockResponse)
   221  		},
   222  		Config: map[channels.Channel]ChannelAuthConfig{
   223  			channels.SyncClusterPrefix: {
   224  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   225  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   226  			},
   227  		},
   228  	}
   229  
   230  	// collections, guarantees & transactions
   231  	authorizationConfigs[CollectionGuarantee] = MsgAuthConfig{
   232  		Name: CollectionGuarantee,
   233  		Type: func() interface{} {
   234  			return new(flow.CollectionGuarantee)
   235  		},
   236  		Config: map[channels.Channel]ChannelAuthConfig{
   237  			channels.PushGuarantees: {
   238  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   239  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   240  			}, // channel alias ReceiveGuarantees = PushGuarantees
   241  		},
   242  	}
   243  	authorizationConfigs[TransactionBody] = MsgAuthConfig{
   244  		Name: TransactionBody,
   245  		Type: func() interface{} {
   246  			return new(flow.TransactionBody)
   247  		},
   248  		Config: map[channels.Channel]ChannelAuthConfig{
   249  			channels.PushTransactions: {
   250  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   251  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   252  			}, // channel alias ReceiveTransactions = PushTransactions
   253  		},
   254  	}
   255  
   256  	// core messages for execution & verification
   257  	authorizationConfigs[ExecutionReceipt] = MsgAuthConfig{
   258  		Name: ExecutionReceipt,
   259  		Type: func() interface{} {
   260  			return new(flow.ExecutionReceipt)
   261  		},
   262  		Config: map[channels.Channel]ChannelAuthConfig{
   263  			channels.PushReceipts: {
   264  				AuthorizedRoles:  flow.RoleList{flow.RoleExecution},
   265  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   266  			}, // channel alias ReceiveReceipts = PushReceipts
   267  		},
   268  	}
   269  	authorizationConfigs[ResultApproval] = MsgAuthConfig{
   270  		Name: ResultApproval,
   271  		Type: func() interface{} {
   272  			return new(flow.ResultApproval)
   273  		},
   274  		Config: map[channels.Channel]ChannelAuthConfig{
   275  			channels.PushApprovals: {
   276  				AuthorizedRoles:  flow.RoleList{flow.RoleVerification},
   277  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   278  			}, // channel alias ReceiveApprovals = PushApprovals
   279  		},
   280  	}
   281  
   282  	// data exchange for execution of blocks
   283  	authorizationConfigs[ChunkDataRequest] = MsgAuthConfig{
   284  		Name: ChunkDataRequest,
   285  		Type: func() interface{} {
   286  			return new(messages.ChunkDataRequest)
   287  		},
   288  		Config: map[channels.Channel]ChannelAuthConfig{
   289  			channels.RequestChunks: {
   290  				AuthorizedRoles:  flow.RoleList{flow.RoleVerification},
   291  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   292  			}, // channel alias RequestChunks = ProvideChunks
   293  		},
   294  	}
   295  	authorizationConfigs[ChunkDataResponse] = MsgAuthConfig{
   296  		Name: ChunkDataResponse,
   297  		Type: func() interface{} {
   298  			return new(messages.ChunkDataResponse)
   299  		},
   300  		Config: map[channels.Channel]ChannelAuthConfig{
   301  			channels.ProvideChunks: {
   302  				AuthorizedRoles:  flow.RoleList{flow.RoleExecution},
   303  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   304  			}, // channel alias RequestChunks = ProvideChunks
   305  		},
   306  	}
   307  
   308  	// result approvals
   309  	authorizationConfigs[ApprovalRequest] = MsgAuthConfig{
   310  		Name: ApprovalRequest,
   311  		Type: func() interface{} {
   312  			return new(messages.ApprovalRequest)
   313  		},
   314  		Config: map[channels.Channel]ChannelAuthConfig{
   315  			channels.RequestApprovalsByChunk: {
   316  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
   317  				AllowedProtocols: Protocols{ProtocolTypePubSub},
   318  			}, // channel alias ProvideApprovalsByChunk  = RequestApprovalsByChunk
   319  		},
   320  	}
   321  	authorizationConfigs[ApprovalResponse] = MsgAuthConfig{
   322  		Name: ApprovalResponse,
   323  		Type: func() interface{} {
   324  			return new(messages.ApprovalResponse)
   325  		},
   326  		Config: map[channels.Channel]ChannelAuthConfig{
   327  			channels.ProvideApprovalsByChunk: {
   328  				AuthorizedRoles:  flow.RoleList{flow.RoleVerification},
   329  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   330  			}, // channel alias ProvideApprovalsByChunk  = RequestApprovalsByChunk
   331  		},
   332  	}
   333  
   334  	// generic entity exchange engines
   335  	authorizationConfigs[EntityRequest] = MsgAuthConfig{
   336  		Name: EntityRequest,
   337  		Type: func() interface{} {
   338  			return new(messages.EntityRequest)
   339  		},
   340  		Config: map[channels.Channel]ChannelAuthConfig{
   341  			channels.RequestReceiptsByBlockID: {
   342  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
   343  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   344  			},
   345  			channels.RequestCollections: {
   346  				AuthorizedRoles:  flow.RoleList{flow.RoleAccess, flow.RoleExecution},
   347  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   348  			},
   349  		},
   350  	}
   351  	authorizationConfigs[EntityResponse] = MsgAuthConfig{
   352  		Name: EntityResponse,
   353  		Type: func() interface{} {
   354  			return new(messages.EntityResponse)
   355  		},
   356  		Config: map[channels.Channel]ChannelAuthConfig{
   357  			channels.ProvideReceiptsByBlockID: {
   358  				AuthorizedRoles:  flow.RoleList{flow.RoleExecution},
   359  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   360  			},
   361  			channels.ProvideCollections: {
   362  				AuthorizedRoles:  flow.RoleList{flow.RoleCollection},
   363  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   364  			},
   365  		},
   366  	}
   367  
   368  	// testing
   369  	authorizationConfigs[TestMessage] = MsgAuthConfig{
   370  		Name: TestMessage,
   371  		Type: func() interface{} {
   372  			return new(message.TestMessage)
   373  		},
   374  		Config: map[channels.Channel]ChannelAuthConfig{
   375  			channels.TestNetworkChannel: {
   376  				AuthorizedRoles:  flow.Roles(),
   377  				AllowedProtocols: Protocols{ProtocolTypePubSub, ProtocolTypeUnicast},
   378  			},
   379  			channels.TestMetricsChannel: {
   380  				AuthorizedRoles:  flow.Roles(),
   381  				AllowedProtocols: Protocols{ProtocolTypePubSub, ProtocolTypeUnicast},
   382  			},
   383  		},
   384  	}
   385  
   386  	// DKG
   387  	authorizationConfigs[DKGMessage] = MsgAuthConfig{
   388  		Name: DKGMessage,
   389  		Type: func() interface{} {
   390  			return new(messages.DKGMessage)
   391  		},
   392  		Config: map[channels.Channel]ChannelAuthConfig{
   393  			channels.DKGCommittee: {
   394  				AuthorizedRoles:  flow.RoleList{flow.RoleConsensus},
   395  				AllowedProtocols: Protocols{ProtocolTypeUnicast},
   396  			},
   397  		},
   398  	}
   399  }
   400  
   401  // GetMessageAuthConfig checks the underlying type and returns the correct
   402  // message auth Config.
   403  // Expected error returns during normal operations:
   404  //   - ErrUnknownMsgType : if underlying type of v does  not match any of the known message types
   405  func GetMessageAuthConfig(v interface{}) (MsgAuthConfig, error) {
   406  	switch v.(type) {
   407  	// consensus
   408  	case *messages.BlockProposal:
   409  		return authorizationConfigs[BlockProposal], nil
   410  	case *messages.BlockVote:
   411  		return authorizationConfigs[BlockVote], nil
   412  	case *messages.TimeoutObject:
   413  		return authorizationConfigs[TimeoutObject], nil
   414  
   415  	// protocol state sync
   416  	case *messages.SyncRequest:
   417  		return authorizationConfigs[SyncRequest], nil
   418  	case *messages.SyncResponse:
   419  		return authorizationConfigs[SyncResponse], nil
   420  	case *messages.RangeRequest:
   421  		return authorizationConfigs[RangeRequest], nil
   422  	case *messages.BatchRequest:
   423  		return authorizationConfigs[BatchRequest], nil
   424  	case *messages.BlockResponse:
   425  		return authorizationConfigs[BlockResponse], nil
   426  
   427  	// cluster consensus
   428  	case *messages.ClusterBlockProposal:
   429  		return authorizationConfigs[ClusterBlockProposal], nil
   430  	case *messages.ClusterBlockVote:
   431  		return authorizationConfigs[ClusterBlockVote], nil
   432  	case *messages.ClusterTimeoutObject:
   433  		return authorizationConfigs[ClusterTimeoutObject], nil
   434  	case *messages.ClusterBlockResponse:
   435  		return authorizationConfigs[ClusterBlockResponse], nil
   436  
   437  	// collections, guarantees & transactions
   438  	case *flow.CollectionGuarantee:
   439  		return authorizationConfigs[CollectionGuarantee], nil
   440  	case *flow.TransactionBody:
   441  		return authorizationConfigs[TransactionBody], nil
   442  
   443  	// core messages for execution & verification
   444  	case *flow.ExecutionReceipt:
   445  		return authorizationConfigs[ExecutionReceipt], nil
   446  	case *flow.ResultApproval:
   447  		return authorizationConfigs[ResultApproval], nil
   448  
   449  	// data exchange for execution of blocks
   450  	case *messages.ChunkDataRequest:
   451  		return authorizationConfigs[ChunkDataRequest], nil
   452  	case *messages.ChunkDataResponse:
   453  		return authorizationConfigs[ChunkDataResponse], nil
   454  
   455  	// result approvals
   456  	case *messages.ApprovalRequest:
   457  		return authorizationConfigs[ApprovalRequest], nil
   458  	case *messages.ApprovalResponse:
   459  		return authorizationConfigs[ApprovalResponse], nil
   460  
   461  	// generic entity exchange engines
   462  	case *messages.EntityRequest:
   463  		return authorizationConfigs[EntityRequest], nil
   464  	case *messages.EntityResponse:
   465  		return authorizationConfigs[EntityResponse], nil
   466  
   467  	// testing
   468  	case *message.TestMessage:
   469  		return authorizationConfigs[TestMessage], nil
   470  
   471  	// dkg
   472  	case *messages.DKGMessage:
   473  		return authorizationConfigs[DKGMessage], nil
   474  
   475  	default:
   476  		return MsgAuthConfig{}, NewUnknownMsgTypeErr(v)
   477  	}
   478  }
   479  
   480  // GetAllMessageAuthConfigs returns all the configured message auth configurations.
   481  func GetAllMessageAuthConfigs() []MsgAuthConfig {
   482  	configs := make([]MsgAuthConfig, len(authorizationConfigs))
   483  
   484  	i := 0
   485  	for _, config := range authorizationConfigs {
   486  		configs[i] = config
   487  		i++
   488  	}
   489  
   490  	return configs
   491  }