diff --git a/common/config/msp/config_util.go b/common/config/msp/config_util.go index 230ab3f0a9d..0b1492147f5 100644 --- a/common/config/msp/config_util.go +++ b/common/config/msp/config_util.go @@ -42,8 +42,9 @@ const ( MSPKey = "MSP" ) -// TemplateGroupMSP creates an MSP ConfigValue at the given configPath -func TemplateGroupMSP(configPath []string, mspConfig *mspprotos.MSPConfig) *cb.ConfigGroup { +// TemplateGroupMSPWithAdminRolePrincipal creates an MSP ConfigValue at the given configPath with Admin policy +// of role type ADMIN if admin==true or MEMBER otherwise +func TemplateGroupMSPWithAdminRolePrincipal(configPath []string, mspConfig *mspprotos.MSPConfig, admin bool) *cb.ConfigGroup { // check that the type for that MSP is supported if mspConfig.Type != int32(msp.FABRIC) { logger.Panicf("Setup error: unsupported msp type %d", mspConfig.Type) @@ -74,10 +75,17 @@ func TemplateGroupMSP(configPath []string, mspConfig *mspprotos.MSPConfig) *cb.C }, } + var adminSigPolicy []byte + if admin { + adminSigPolicy = utils.MarshalOrPanic(cauthdsl.SignedByMspAdmin(mspID)) + } else { + adminSigPolicy = utils.MarshalOrPanic(cauthdsl.SignedByMspMember(mspID)) + } + adminPolicy := &cb.ConfigPolicy{ Policy: &cb.Policy{ Type: int32(cb.Policy_SIGNATURE), - Policy: utils.MarshalOrPanic(cauthdsl.SignedByMspAdmin(mspID)), + Policy: adminSigPolicy, }, } @@ -96,3 +104,8 @@ func TemplateGroupMSP(configPath []string, mspConfig *mspprotos.MSPConfig) *cb.C intermediate.Policies[WritersPolicyKey] = memberPolicy return result } + +// TemplateGroupMSP creates an MSP ConfigValue at the given configPath +func TemplateGroupMSP(configPath []string, mspConfig *mspprotos.MSPConfig) *cb.ConfigGroup { + return TemplateGroupMSPWithAdminRolePrincipal(configPath, mspConfig, true) +} diff --git a/common/configtx/tool/localconfig/config.go b/common/configtx/tool/localconfig/config.go index 405b34e6dd6..eee2f65fc28 100644 --- a/common/configtx/tool/localconfig/config.go +++ b/common/configtx/tool/localconfig/config.go @@ -61,6 +61,11 @@ const ( SampleSingleMSPSoloProfile = "SampleSingleMSPSolo" // SampleConsortiumName is the sample consortium from the sample configtx.yaml SampleConsortiumName = "SampleConsortium" + + // AdminRoleAdminPrincipal is set as AdminRole to cause the MSP role of type Admin to be used as the admin principal default + AdminRoleAdminPrincipal = "Role.ADMIN" + // MemberRoleAdminPrincipal is set as AdminRole to cause the MSP role of type Member to be used as the admin principal default + MemberRoleAdminPrincipal = "Role.MEMBER" ) // TopLevel consists of the structs used by the configtxgen tool. @@ -73,6 +78,7 @@ type TopLevel struct { // Profile encodes orderer/application configuration combinations for the configtxgen tool. type Profile struct { + Consortium string `yaml:"Consortium"` Application *Application `yaml:"Application"` Orderer *Orderer `yaml:"Orderer"` Consortiums map[string]*Consortium `yaml:"Consortiums"` @@ -90,10 +96,11 @@ type Application struct { // Organization encodes the organization-level configuration needed in config transactions. type Organization struct { - Name string `yaml:"Name"` - ID string `yaml:"ID"` - MSPDir string `yaml:"MSPDir"` - BCCSP *bccsp.FactoryOpts `yaml:"BCCSP"` + Name string `yaml:"Name"` + ID string `yaml:"ID"` + MSPDir string `yaml:"MSPDir"` + AdminPrincipal string `yaml:"AdminPrincipal"` + BCCSP *bccsp.FactoryOpts `yaml:"BCCSP"` // Note: Viper deserialization does not seem to care for // embedding of types, so we use one organization struct @@ -212,6 +219,37 @@ func (p *Profile) completeInitialization(configDir string) { } func (p *Profile) initDefaults() { + if p.Orderer != nil { + for _, org := range p.Orderer.Organizations { + if org.AdminPrincipal == "" { + org.AdminPrincipal = AdminRoleAdminPrincipal + } + } + } + + if p.Application != nil { + for _, org := range p.Application.Organizations { + if org.AdminPrincipal == "" { + org.AdminPrincipal = AdminRoleAdminPrincipal + } + } + } + + if p.Consortiums != nil { + for _, consortium := range p.Consortiums { + for _, org := range consortium.Organizations { + if org.AdminPrincipal == "" { + org.AdminPrincipal = AdminRoleAdminPrincipal + } + } + } + } + + // Some profiles will not define orderer parameters + if p.Orderer == nil { + return + } + for { switch { case p.Orderer.OrdererType == "": diff --git a/common/configtx/tool/provisional/provisional.go b/common/configtx/tool/provisional/provisional.go index 082e8cc58b5..a91700a1043 100644 --- a/common/configtx/tool/provisional/provisional.go +++ b/common/configtx/tool/provisional/provisional.go @@ -134,7 +134,11 @@ func New(conf *genesisconfig.Profile) Generator { if err != nil { logger.Panicf("1 - Error loading MSP configuration for org %s: %s", org.Name, err) } - bs.ordererGroups = append(bs.ordererGroups, configvaluesmsp.TemplateGroupMSP([]string{config.OrdererGroupKey, org.Name}, mspConfig)) + bs.ordererGroups = append(bs.ordererGroups, + configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal([]string{config.OrdererGroupKey, org.Name}, + mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal, + ), + ) } switch conf.Orderer.OrdererType { @@ -165,7 +169,11 @@ func New(conf *genesisconfig.Profile) Generator { logger.Panicf("2- Error loading MSP configuration for org %s: %s", org.Name, err) } - bs.applicationGroups = append(bs.applicationGroups, configvaluesmsp.TemplateGroupMSP([]string{config.ApplicationGroupKey, org.Name}, mspConfig)) + bs.applicationGroups = append(bs.applicationGroups, + configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal([]string{config.ApplicationGroupKey, org.Name}, + mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal, + ), + ) var anchorProtos []*pb.AnchorPeer for _, anchorPeer := range org.AnchorPeers { anchorProtos = append(anchorProtos, &pb.AnchorPeer{ @@ -195,7 +203,12 @@ func New(conf *genesisconfig.Profile) Generator { if err != nil { logger.Panicf("3 - Error loading MSP configuration for org %s: %s", org.Name, err) } - bs.consortiumsGroups = append(bs.consortiumsGroups, configvaluesmsp.TemplateGroupMSP([]string{config.ConsortiumsGroupKey, consortiumName, org.Name}, mspConfig)) + bs.consortiumsGroups = append(bs.consortiumsGroups, + configvaluesmsp.TemplateGroupMSPWithAdminRolePrincipal( + []string{config.ConsortiumsGroupKey, consortiumName, org.Name}, + mspConfig, org.AdminPrincipal == genesisconfig.AdminRoleAdminPrincipal, + ), + ) } } } diff --git a/sampleconfig/configtx.yaml b/sampleconfig/configtx.yaml index 32ec484f83f..c5386c2a8c9 100644 --- a/sampleconfig/configtx.yaml +++ b/sampleconfig/configtx.yaml @@ -73,6 +73,11 @@ Organizations: # MSPDir is the filesystem path which contains the MSP configuration. MSPDir: msp + # AdminPrincipal dictates the type of principal used for an organization's Admins policy + # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal + # of role type ADMIN and role type MEMBER respectively + AdminPrincipal: Role.ADMIN + # BCCSP: Select which crypto implementation or library to use for the # blockchain crypto service provider. BCCSP: