|
| 1 | +/* |
| 2 | +Copyright IBM Corp. 2016 All Rights Reserved. |
| 3 | +
|
| 4 | +SPDX-License-Identifier: Apache-2.0 |
| 5 | +*/ |
| 6 | + |
| 7 | +package encoder |
| 8 | + |
| 9 | +import ( |
| 10 | + "github.com/hyperledger/fabric/common/cauthdsl" |
| 11 | + "github.com/hyperledger/fabric/common/channelconfig" |
| 12 | + "github.com/hyperledger/fabric/common/flogging" |
| 13 | + "github.com/hyperledger/fabric/common/policies" |
| 14 | + genesisconfig "github.com/hyperledger/fabric/common/tools/configtxgen/localconfig" |
| 15 | + "github.com/hyperledger/fabric/msp" |
| 16 | + cb "github.com/hyperledger/fabric/protos/common" |
| 17 | + pb "github.com/hyperledger/fabric/protos/peer" |
| 18 | + "github.com/hyperledger/fabric/protos/utils" |
| 19 | + |
| 20 | + "github.com/pkg/errors" |
| 21 | +) |
| 22 | + |
| 23 | +const ( |
| 24 | + pkgLogID = "common/tools/configtxgen/encoder" |
| 25 | + ordererAdminsPolicyName = "/Channel/Orderer/Admins" |
| 26 | +) |
| 27 | + |
| 28 | +var logger = flogging.MustGetLogger(pkgLogID) |
| 29 | + |
| 30 | +func init() { |
| 31 | + flogging.SetModuleLevel(pkgLogID, "info") |
| 32 | +} |
| 33 | + |
| 34 | +const ( |
| 35 | + // ConsensusTypeSolo identifies the solo consensus implementation. |
| 36 | + ConsensusTypeSolo = "solo" |
| 37 | + // ConsensusTypeKafka identifies the Kafka-based consensus implementation. |
| 38 | + ConsensusTypeKafka = "kafka" |
| 39 | + |
| 40 | + // BlockValidationPolicyKey TODO |
| 41 | + BlockValidationPolicyKey = "BlockValidation" |
| 42 | + |
| 43 | + // OrdererAdminsPolicy is the absolute path to the orderer admins policy |
| 44 | + OrdererAdminsPolicy = "/Channel/Orderer/Admins" |
| 45 | +) |
| 46 | + |
| 47 | +func addValue(cg *cb.ConfigGroup, value channelconfig.ConfigValue, modPolicy string) { |
| 48 | + cg.Values[value.Key()] = &cb.ConfigValue{ |
| 49 | + Value: utils.MarshalOrPanic(value.Value()), |
| 50 | + ModPolicy: modPolicy, |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +func addPolicy(cg *cb.ConfigGroup, policy policies.ConfigPolicy, modPolicy string) { |
| 55 | + cg.Policies[policy.Key()] = &cb.ConfigPolicy{ |
| 56 | + Policy: policy.Value(), |
| 57 | + ModPolicy: modPolicy, |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +// addImplicitMetaPolicyDefaults adds the Readers/Writers/Admins policies, with Any/Any/Majority rules respectively. |
| 62 | +func addImplicitMetaPolicyDefaults(cg *cb.ConfigGroup) { |
| 63 | + addPolicy(cg, policies.ImplicitMetaMajorityPolicy(channelconfig.AdminsPolicyKey), channelconfig.AdminsPolicyKey) |
| 64 | + addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.ReadersPolicyKey), channelconfig.AdminsPolicyKey) |
| 65 | + addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey), channelconfig.AdminsPolicyKey) |
| 66 | +} |
| 67 | + |
| 68 | +// addSignaturePolicyDefaults adds the Readers/Writers/Admins policies as signature policies requiring one signature from the given mspID. |
| 69 | +// If devMode is set to true, the Admins policy will accept arbitrary user certs for admin functions, otherwise it requires the cert satisfies |
| 70 | +// the admin role principal. |
| 71 | +func addSignaturePolicyDefaults(cg *cb.ConfigGroup, mspID string, devMode bool) { |
| 72 | + if devMode { |
| 73 | + addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey) |
| 74 | + } else { |
| 75 | + addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspAdmin(mspID)), channelconfig.AdminsPolicyKey) |
| 76 | + } |
| 77 | + addPolicy(cg, policies.SignaturePolicy(channelconfig.ReadersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey) |
| 78 | + addPolicy(cg, policies.SignaturePolicy(channelconfig.WritersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey) |
| 79 | +} |
| 80 | + |
| 81 | +// NewChannelGroup defines the root of the channel configuration. It defines basic operating principles like the hashing |
| 82 | +// algorithm used for the blocks, as well as the location of the ordering service. It will recursively call into the |
| 83 | +// NewOrdererGroup, NewConsortiumsGroup, and NewApplicationGroup depending on whether these sub-elements are set in the |
| 84 | +// configuration. All mod_policy values are set to "Admins" for this group, with the exception of the OrdererAddresses |
| 85 | +// value which is set to "/Channel/Orderer/Admins". |
| 86 | +func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) { |
| 87 | + if conf.Orderer == nil { |
| 88 | + return nil, errors.New("missing orderer config section") |
| 89 | + } |
| 90 | + |
| 91 | + channelGroup := cb.NewConfigGroup() |
| 92 | + addImplicitMetaPolicyDefaults(channelGroup) |
| 93 | + addValue(channelGroup, channelconfig.HashingAlgorithmValue(), channelconfig.AdminsPolicyKey) |
| 94 | + addValue(channelGroup, channelconfig.BlockDataHashingStructureValue(), channelconfig.AdminsPolicyKey) |
| 95 | + addValue(channelGroup, channelconfig.OrdererAddressesValue(conf.Orderer.Addresses), ordererAdminsPolicyName) |
| 96 | + |
| 97 | + if conf.Consortium != "" { |
| 98 | + addValue(channelGroup, channelconfig.ConsortiumValue(conf.Consortium), channelconfig.AdminsPolicyKey) |
| 99 | + } |
| 100 | + |
| 101 | + if len(conf.Capabilities) > 0 { |
| 102 | + addValue(channelGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) |
| 103 | + } |
| 104 | + |
| 105 | + var err error |
| 106 | + channelGroup.Groups[channelconfig.OrdererGroupKey], err = NewOrdererGroup(conf.Orderer) |
| 107 | + if err != nil { |
| 108 | + return nil, errors.Wrap(err, "could not create orderer group") |
| 109 | + } |
| 110 | + |
| 111 | + if conf.Application != nil { |
| 112 | + channelGroup.Groups[channelconfig.ApplicationGroupKey], err = NewApplicationGroup(conf.Application) |
| 113 | + if err != nil { |
| 114 | + return nil, errors.Wrap(err, "could not create application group") |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + if conf.Consortiums != nil { |
| 119 | + channelGroup.Groups[channelconfig.ConsortiumsGroupKey], err = NewConsortiumsGroup(conf.Consortiums) |
| 120 | + if err != nil { |
| 121 | + return nil, errors.Wrap(err, "could not create consortiums group") |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + channelGroup.ModPolicy = channelconfig.AdminsPolicyKey |
| 126 | + return channelGroup, nil |
| 127 | +} |
| 128 | + |
| 129 | +// NewOrdererGroup returns the orderer component of the channel configuration. It defines parameters of the ordering service |
| 130 | +// about how large blocks should be, how frequently they should be emitted, etc. as well as the organizations of the ordering network. |
| 131 | +// It sets the mod_policy of all elements to "Admins". This group is always present in any channel configuration. |
| 132 | +func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) { |
| 133 | + ordererGroup := cb.NewConfigGroup() |
| 134 | + addImplicitMetaPolicyDefaults(ordererGroup) |
| 135 | + ordererGroup.Policies[BlockValidationPolicyKey] = &cb.ConfigPolicy{ |
| 136 | + Policy: policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey).Value(), |
| 137 | + ModPolicy: channelconfig.AdminsPolicyKey, |
| 138 | + } |
| 139 | + addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType), channelconfig.AdminsPolicyKey) |
| 140 | + addValue(ordererGroup, channelconfig.BatchSizeValue( |
| 141 | + conf.BatchSize.MaxMessageCount, |
| 142 | + conf.BatchSize.AbsoluteMaxBytes, |
| 143 | + conf.BatchSize.PreferredMaxBytes, |
| 144 | + ), channelconfig.AdminsPolicyKey) |
| 145 | + addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey) |
| 146 | + addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey) |
| 147 | + |
| 148 | + if len(conf.Capabilities) > 0 { |
| 149 | + addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) |
| 150 | + } |
| 151 | + |
| 152 | + switch conf.OrdererType { |
| 153 | + case ConsensusTypeSolo: |
| 154 | + case ConsensusTypeKafka: |
| 155 | + addValue(ordererGroup, channelconfig.KafkaBrokersValue(conf.Kafka.Brokers), channelconfig.AdminsPolicyKey) |
| 156 | + default: |
| 157 | + return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType) |
| 158 | + } |
| 159 | + |
| 160 | + for _, org := range conf.Organizations { |
| 161 | + var err error |
| 162 | + ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org) |
| 163 | + if err != nil { |
| 164 | + return nil, errors.Wrap(err, "failed to create orderer org") |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | + ordererGroup.ModPolicy = channelconfig.AdminsPolicyKey |
| 169 | + return ordererGroup, nil |
| 170 | +} |
| 171 | + |
| 172 | +// NewOrdererOrgGroup returns an orderer org component of the channel configuration. It defines the crypto material for the |
| 173 | +// organization (its MSP). It sets the mod_policy of all elements to "Admins". |
| 174 | +func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) { |
| 175 | + mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID) |
| 176 | + if err != nil { |
| 177 | + return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org %s: %s", conf.Name) |
| 178 | + } |
| 179 | + |
| 180 | + ordererOrgGroup := cb.NewConfigGroup() |
| 181 | + addSignaturePolicyDefaults(ordererOrgGroup, conf.ID, conf.AdminPrincipal != genesisconfig.AdminRoleAdminPrincipal) |
| 182 | + addValue(ordererOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey) |
| 183 | + |
| 184 | + ordererOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey |
| 185 | + return ordererOrgGroup, nil |
| 186 | +} |
| 187 | + |
| 188 | +// NewApplicationGroup returns the application component of the channel configuration. It defines the organizations which are involved |
| 189 | +// in application logic like chaincodes, and how these members may interact with the orderer. It sets the mod_policy of all elements to "Admins". |
| 190 | +func NewApplicationGroup(conf *genesisconfig.Application) (*cb.ConfigGroup, error) { |
| 191 | + applicationGroup := cb.NewConfigGroup() |
| 192 | + addImplicitMetaPolicyDefaults(applicationGroup) |
| 193 | + |
| 194 | + if len(conf.Capabilities) > 0 { |
| 195 | + addValue(applicationGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) |
| 196 | + } |
| 197 | + |
| 198 | + for _, org := range conf.Organizations { |
| 199 | + var err error |
| 200 | + applicationGroup.Groups[org.Name], err = NewApplicationOrgGroup(org) |
| 201 | + if err != nil { |
| 202 | + return nil, errors.Wrap(err, "failed to create application org") |
| 203 | + } |
| 204 | + } |
| 205 | + |
| 206 | + applicationGroup.ModPolicy = channelconfig.AdminsPolicyKey |
| 207 | + return applicationGroup, nil |
| 208 | +} |
| 209 | + |
| 210 | +// NewApplicationOrgGroup returns an application org component of the channel configuration. It defines the crypto material for the organization |
| 211 | +// (its MSP) as well as its anchor peers for use by the gossip network. It sets the mod_policy of all elements to "Admins". |
| 212 | +func NewApplicationOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) { |
| 213 | + mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID) |
| 214 | + if err != nil { |
| 215 | + return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org %s: %s", conf.Name) |
| 216 | + } |
| 217 | + |
| 218 | + applicationOrgGroup := cb.NewConfigGroup() |
| 219 | + addSignaturePolicyDefaults(applicationOrgGroup, conf.ID, conf.AdminPrincipal != genesisconfig.AdminRoleAdminPrincipal) |
| 220 | + addValue(applicationOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey) |
| 221 | + |
| 222 | + var anchorProtos []*pb.AnchorPeer |
| 223 | + for _, anchorPeer := range conf.AnchorPeers { |
| 224 | + anchorProtos = append(anchorProtos, &pb.AnchorPeer{ |
| 225 | + Host: anchorPeer.Host, |
| 226 | + Port: int32(anchorPeer.Port), |
| 227 | + }) |
| 228 | + } |
| 229 | + addValue(applicationOrgGroup, channelconfig.AnchorPeersValue(anchorProtos), channelconfig.AdminsPolicyKey) |
| 230 | + |
| 231 | + applicationOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey |
| 232 | + return applicationOrgGroup, nil |
| 233 | +} |
| 234 | + |
| 235 | +// NewConsortiumsGroup returns the consortiums component of the channel configuration. This element is only defined for the ordering system channel. |
| 236 | +// It sets the mod_policy for all elements to "/Channel/Orderer/Admins". |
| 237 | +func NewConsortiumsGroup(conf map[string]*genesisconfig.Consortium) (*cb.ConfigGroup, error) { |
| 238 | + consortiumsGroup := cb.NewConfigGroup() |
| 239 | + // This policy is not referenced anywhere, it is only used as part of the implicit meta policy rule at the channel level, so this setting |
| 240 | + // effectively degrades control of the ordering system channel to the ordering admins |
| 241 | + addPolicy(consortiumsGroup, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.AcceptAllPolicy), ordererAdminsPolicyName) |
| 242 | + |
| 243 | + for consortiumName, consortium := range conf { |
| 244 | + var err error |
| 245 | + consortiumsGroup.Groups[consortiumName], err = NewConsortiumGroup(consortium) |
| 246 | + if err != nil { |
| 247 | + return nil, errors.Wrapf(err, "failed to create consortium %s", consortiumName) |
| 248 | + } |
| 249 | + } |
| 250 | + |
| 251 | + consortiumsGroup.ModPolicy = ordererAdminsPolicyName |
| 252 | + return consortiumsGroup, nil |
| 253 | +} |
| 254 | + |
| 255 | +// NewConsortiums returns a consortiums component of the channel configuration. Each consortium defines the organizations which may be involved in channel |
| 256 | +// creation, as well as the channel creation policy the orderer checks at channel creation time to authorize the action. It sets the mod_policy of all |
| 257 | +// elements to "/Channel/Orderer/Admins". |
| 258 | +func NewConsortiumGroup(conf *genesisconfig.Consortium) (*cb.ConfigGroup, error) { |
| 259 | + consortiumGroup := cb.NewConfigGroup() |
| 260 | + |
| 261 | + for _, org := range conf.Organizations { |
| 262 | + var err error |
| 263 | + // Note, NewOrdererOrgGroup is correct here, as the structure is identical |
| 264 | + consortiumGroup.Groups[org.Name], err = NewOrdererOrgGroup(org) |
| 265 | + if err != nil { |
| 266 | + return nil, errors.Wrap(err, "failed to create consortium org") |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + addValue(consortiumGroup, channelconfig.ChannelCreationPolicyValue(policies.ImplicitMetaAnyPolicy(channelconfig.AdminsPolicyKey).Value()), ordererAdminsPolicyName) |
| 271 | + |
| 272 | + consortiumGroup.ModPolicy = ordererAdminsPolicyName |
| 273 | + return consortiumGroup, nil |
| 274 | +} |
0 commit comments