From f2e9e6e7b307a25dc4738e97a1ffb08daea4f6dc Mon Sep 17 00:00:00 2001 From: Will Lahti Date: Fri, 2 Oct 2020 11:03:05 -0400 Subject: [PATCH] Allow BCCSP config to be set using env var (#1900) FAB-17969 Signed-off-by: Tiffany Harris Signed-off-by: Will Lahti --- bccsp/factory/nopkcs11.go | 6 -- bccsp/factory/opts.go | 27 ++--- bccsp/factory/pkcs11.go | 8 -- common/viperutil/config_util.go | 2 +- integration/nwo/core_template.go | 6 ++ integration/nwo/orderer_template.go | 6 ++ integration/pkcs11/pkcs11_suite_test.go | 62 +++++++++++ integration/pkcs11/pkcs11_test.go | 138 +++++++++++++----------- internal/peer/common/common.go | 41 +++++++ internal/peer/common/common_test.go | 57 ++++++++++ 10 files changed, 263 insertions(+), 90 deletions(-) diff --git a/bccsp/factory/nopkcs11.go b/bccsp/factory/nopkcs11.go index 7896cf2bb0d..012ab5d2bfc 100644 --- a/bccsp/factory/nopkcs11.go +++ b/bccsp/factory/nopkcs11.go @@ -15,12 +15,6 @@ import ( const pkcs11Enabled = false -// FactoryOpts holds configuration information used to initialize factory implementations -type FactoryOpts struct { - ProviderName string `mapstructure:"default" json:"default" yaml:"Default"` - SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SW,omitempty"` -} - // InitFactories must be called before using factory interfaces // It is acceptable to call with config = nil, in which case // some defaults will get used diff --git a/bccsp/factory/opts.go b/bccsp/factory/opts.go index be0a45dd2a1..5042c615105 100644 --- a/bccsp/factory/opts.go +++ b/bccsp/factory/opts.go @@ -1,21 +1,20 @@ /* -Copyright IBM Corp. 2016 All Rights Reserved. +Copyright IBM Corp. All Rights Reserved. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. +SPDX-License-Identifier: Apache-2.0 */ package factory +import "github.com/hyperledger/fabric/bccsp/pkcs11" + +// FactoryOpts holds configuration information used to initialize factory implementations +type FactoryOpts struct { + ProviderName string `mapstructure:"default" json:"default" yaml:"Default"` + SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SW,omitempty"` + Pkcs11Opts *pkcs11.PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"` +} + // GetDefaultOpts offers a default implementation for Opts // returns a new instance every time func GetDefaultOpts() *FactoryOpts { @@ -26,6 +25,10 @@ func GetDefaultOpts() *FactoryOpts { SecLevel: 256, Ephemeral: true, }, + Pkcs11Opts: &pkcs11.PKCS11Opts{ + HashFamily: "SHA2", + SecLevel: 256, + }, } } diff --git a/bccsp/factory/pkcs11.go b/bccsp/factory/pkcs11.go index a0a1932dac2..2aad94fbbb6 100644 --- a/bccsp/factory/pkcs11.go +++ b/bccsp/factory/pkcs11.go @@ -10,19 +10,11 @@ package factory import ( "github.com/hyperledger/fabric/bccsp" - "github.com/hyperledger/fabric/bccsp/pkcs11" "github.com/pkg/errors" ) const pkcs11Enabled = false -// FactoryOpts holds configuration information used to initialize factory implementations -type FactoryOpts struct { - ProviderName string `mapstructure:"default" json:"default" yaml:"Default"` - SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SW,omitempty"` - Pkcs11Opts *pkcs11.PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"` -} - // InitFactories must be called before using factory interfaces // It is acceptable to call with config = nil, in which case // some defaults will get used diff --git a/common/viperutil/config_util.go b/common/viperutil/config_util.go index 64326fff0b0..7530e1d2280 100644 --- a/common/viperutil/config_util.go +++ b/common/viperutil/config_util.go @@ -306,7 +306,7 @@ func bccspHook(f reflect.Type, t reflect.Type, data interface{}) (interface{}, e err := mapstructure.WeakDecode(data, config) if err != nil { - return nil, errors.Wrap(err, "could not decode bcssp type") + return nil, errors.Wrap(err, "could not decode bccsp type") } return config, nil diff --git a/integration/nwo/core_template.go b/integration/nwo/core_template.go index cbd1975aef7..c6bf34f439f 100644 --- a/integration/nwo/core_template.go +++ b/integration/nwo/core_template.go @@ -110,6 +110,12 @@ peer: Security: 256 FileKeyStore: KeyStore: + PKCS11: + Hash: SHA2 + Security: 256 + Library: + Label: + Pin: mspConfigPath: {{ .PeerLocalMSPDir Peer }} localMspId: {{ (.Organization Peer.Organization).MSPID }} deliveryclient: diff --git a/integration/nwo/orderer_template.go b/integration/nwo/orderer_template.go index c23bf12d314..b077a575b49 100644 --- a/integration/nwo/orderer_template.go +++ b/integration/nwo/orderer_template.go @@ -49,6 +49,12 @@ General: Security: 256 FileKeyStore: KeyStore: + PKCS11: + Hash: SHA2 + Security: 256 + Library: + Label: + Pin: Authentication: TimeWindow: 15m FileLedger: diff --git a/integration/pkcs11/pkcs11_suite_test.go b/integration/pkcs11/pkcs11_suite_test.go index eb35aa35d2b..ea095e1d7b4 100644 --- a/integration/pkcs11/pkcs11_suite_test.go +++ b/integration/pkcs11/pkcs11_suite_test.go @@ -14,6 +14,8 @@ import ( "github.com/hyperledger/fabric/integration" "github.com/hyperledger/fabric/integration/nwo" "github.com/hyperledger/fabric/integration/nwo/commands" + "github.com/hyperledger/fabric/integration/nwo/fabricconfig" + "github.com/miekg/pkcs11" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gbytes" @@ -32,6 +34,9 @@ func TestPKCS11(t *testing.T) { var ( buildServer *nwo.BuildServer components *nwo.Components + ctx *pkcs11.Ctx + sess pkcs11.SessionHandle + bccspConfig *fabricconfig.BCCSP ) var _ = SynchronizedBeforeSuite(func() []byte { @@ -41,6 +46,9 @@ var _ = SynchronizedBeforeSuite(func() []byte { components = buildServer.Components() payload, err := json.Marshal(components) Expect(err).NotTo(HaveOccurred()) + + setupPKCS11() + return payload }, func(payload []byte) { err := json.Unmarshal(payload, &components) @@ -50,12 +58,66 @@ var _ = SynchronizedBeforeSuite(func() []byte { var _ = SynchronizedAfterSuite(func() { }, func() { buildServer.Shutdown() + ctx.Destroy() + ctx.CloseSession(sess) }) func StartPort() int { return integration.PKCS11Port.StartPortForNode() } +func setupPKCS11() { + lib, pin, label := bpkcs11.FindPKCS11Lib() + ctx, sess = setupPKCS11Ctx(lib, label, pin) + bccspConfig = &fabricconfig.BCCSP{ + Default: "PKCS11", + PKCS11: &fabricconfig.PKCS11{ + Security: 256, + Hash: "SHA2", + Pin: pin, + Label: label, + Library: lib, + }, + } +} + +// Creates pkcs11 context and session +func setupPKCS11Ctx(lib, label, pin string) (*pkcs11.Ctx, pkcs11.SessionHandle) { + ctx := pkcs11.New(lib) + + err := ctx.Initialize() + Expect(err).NotTo(HaveOccurred()) + + slot := findPKCS11Slot(ctx, label) + Expect(slot).Should(BeNumerically(">", 0), "Could not find slot with label %s", label) + + sess, err := ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION) + Expect(err).NotTo(HaveOccurred()) + + // Login + err = ctx.Login(sess, pkcs11.CKU_USER, pin) + Expect(err).NotTo(HaveOccurred()) + + return ctx, sess +} + +// Identifies pkcs11 slot using specified label +func findPKCS11Slot(ctx *pkcs11.Ctx, label string) uint { + slots, err := ctx.GetSlotList(true) + Expect(err).NotTo(HaveOccurred()) + + for _, s := range slots { + tokInfo, err := ctx.GetTokenInfo(s) + Expect(err).NotTo(HaveOccurred()) + + if tokInfo.Label == label { + return s + } + } + + return 0 +} + func runQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) { By("querying the chaincode") sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{ diff --git a/integration/pkcs11/pkcs11_test.go b/integration/pkcs11/pkcs11_test.go index f8105543d69..7aa3f8fe8f5 100644 --- a/integration/pkcs11/pkcs11_test.go +++ b/integration/pkcs11/pkcs11_test.go @@ -21,10 +21,10 @@ import ( "math/big" "os" "path/filepath" + "strconv" "syscall" "time" - bpkcs11 "github.com/hyperledger/fabric/bccsp/pkcs11" "github.com/hyperledger/fabric/integration/nwo" "github.com/hyperledger/fabric/integration/nwo/fabricconfig" "github.com/miekg/pkcs11" @@ -50,12 +50,7 @@ var _ = Describe("PKCS11 enabled network", func() { network.Bootstrap() By("configuring PKCS11 artifacts") - setupPKCS11(network) - - By("starting fabric processes") - networkRunner := network.NetworkGroupRunner() - process = ifrit.Invoke(networkRunner) - Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) + configurePKCS11(network) }) AfterEach(func() { @@ -67,7 +62,14 @@ var _ = Describe("PKCS11 enabled network", func() { os.RemoveAll(tempDir) }) - It("executes transactions against a basic solo network", func() { + It("executes transactions against a basic solo network using yaml config", func() { + setPKCS11Config(network, bccspConfig) + + By("starting fabric processes") + networkRunner := network.NetworkGroupRunner() + process = ifrit.Invoke(networkRunner) + Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) + chaincode := nwo.Chaincode{ Name: "mycc", Version: "0.0", @@ -88,30 +90,44 @@ var _ = Describe("PKCS11 enabled network", func() { nwo.DeployChaincode(network, "testchannel", orderer, chaincode) runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel") }) -}) -func setupPKCS11(network *nwo.Network) { - lib, pin, label := bpkcs11.FindPKCS11Lib() + It("executes transactions against a basic solo network using environment variable config", func() { + envCleanup := setPKCS11ConfigWithEnvVariables(network, bccspConfig) + defer envCleanup() + + By("starting fabric processes") + networkRunner := network.NetworkGroupRunner() + process = ifrit.Invoke(networkRunner) + Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) + + chaincode := nwo.Chaincode{ + Name: "mycc", + Version: "0.0", + Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/simple/cmd"), + Lang: "binary", + PackageFile: filepath.Join(tempDir, "simplecc.tar.gz"), + Ctor: `{"Args":["init","a","100","b","200"]}`, + SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`, + Sequence: "1", + InitRequired: true, + Label: "my_prebuilt_chaincode", + } + + orderer := network.Orderer("orderer") + network.CreateAndJoinChannels(orderer) - By("establishing a PKCS11 session") - ctx, sess := setupPKCS11Ctx(lib, label, pin) - defer ctx.Destroy() - defer ctx.CloseSession(sess) + nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.PeersWithChannel("testchannel")...) + nwo.DeployChaincode(network, "testchannel", orderer, chaincode) + runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel") + }) +}) +func configurePKCS11(network *nwo.Network) { configurePeerPKCS11(ctx, sess, network) configureOrdererPKCS11(ctx, sess, network) +} - bccspConfig := &fabricconfig.BCCSP{ - Default: "PKCS11", - PKCS11: &fabricconfig.PKCS11{ - Security: 256, - Hash: "SHA2", - Pin: pin, - Label: label, - Library: lib, - }, - } - +func setPKCS11Config(network *nwo.Network, bccspConfig *fabricconfig.BCCSP) { By("updating bccsp peer config") for _, peer := range network.Peers { peerConfig := network.ReadPeerConfig(peer) @@ -126,6 +142,39 @@ func setupPKCS11(network *nwo.Network) { network.WriteOrdererConfig(orderer, ordererConfig) } +func setPKCS11ConfigWithEnvVariables(network *nwo.Network, bccspConfig *fabricconfig.BCCSP) (cleanup func()) { + By("setting bccsp peer config via environment variables") + os.Setenv("CORE_PEER_BCCSP_DEFAULT", bccspConfig.Default) + os.Setenv("CORE_PEER_BCCSP_PKCS11_SECURITY", strconv.Itoa(bccspConfig.PKCS11.Security)) + os.Setenv("CORE_PEER_BCCSP_PKCS11_HASH", bccspConfig.PKCS11.Hash) + os.Setenv("CORE_PEER_BCCSP_PKCS11_PIN", bccspConfig.PKCS11.Pin) + os.Setenv("CORE_PEER_BCCSP_PKCS11_LABEL", bccspConfig.PKCS11.Label) + os.Setenv("CORE_PEER_BCCSP_PKCS11_LIBRARY", bccspConfig.PKCS11.Library) + + By("setting bccsp orderer config via environment variables") + os.Setenv("ORDERER_GENERAL_BCCSP_DEFAULT", bccspConfig.Default) + os.Setenv("ORDERER_GENERAL_BCCSP_PKCS11_SECURITY", strconv.Itoa(bccspConfig.PKCS11.Security)) + os.Setenv("ORDERER_GENERAL_BCCSP_PKCS11_HASH", bccspConfig.PKCS11.Hash) + os.Setenv("ORDERER_GENERAL_BCCSP_PKCS11_PIN", bccspConfig.PKCS11.Pin) + os.Setenv("ORDERER_GENERAL_BCCSP_PKCS11_LABEL", bccspConfig.PKCS11.Label) + os.Setenv("ORDERER_GENERAL_BCCSP_PKCS11_LIBRARY", bccspConfig.PKCS11.Library) + + return func() { + os.Unsetenv("CORE_PEER_BCCSP_DEFAULT") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_SECURITY") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_HASH") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_PIN") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_LABEL") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_LIBRARY") + os.Unsetenv("ORDERER_GENERAL_BCCSP_DEFAULT") + os.Unsetenv("ORDERER_GENERAL_BCCSP_PKCS11_SECURITY") + os.Unsetenv("ORDERER_GENERAL_BCCSP_PKCS11_HASH") + os.Unsetenv("ORDERER_GENERAL_BCCSP_PKCS11_PIN") + os.Unsetenv("ORDERER_GENERAL_BCCSP_PKCS11_LABEL") + os.Unsetenv("ORDERER_GENERAL_BCCSP_PKCS11_LIBRARY") + } +} + func configurePeerPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network *nwo.Network) { for _, peer := range network.Peers { orgName := peer.Organization @@ -180,43 +229,6 @@ func configureOrdererPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network updateMSPFolder(orgAdminMSPPath, fmt.Sprintf("Admin@%s-cert.pem", domain), newAdminPemCert) } -// Creates pkcs11 context and session -func setupPKCS11Ctx(lib, label, pin string) (*pkcs11.Ctx, pkcs11.SessionHandle) { - ctx := pkcs11.New(lib) - - err := ctx.Initialize() - Expect(err).NotTo(HaveOccurred()) - - slot := findPKCS11Slot(ctx, label) - Expect(slot).Should(BeNumerically(">", 0), "Could not find slot with label %s", label) - - sess, err := ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION) - Expect(err).NotTo(HaveOccurred()) - - // Login - err = ctx.Login(sess, pkcs11.CKU_USER, pin) - Expect(err).NotTo(HaveOccurred()) - - return ctx, sess -} - -// Identifies pkcs11 slot using specified label -func findPKCS11Slot(ctx *pkcs11.Ctx, label string) uint { - slots, err := ctx.GetSlotList(true) - Expect(err).NotTo(HaveOccurred()) - - for _, s := range slots { - tokInfo, err := ctx.GetTokenInfo(s) - Expect(err).NotTo(HaveOccurred()) - - if tokInfo.Label == label { - return s - } - } - - return 0 -} - // Creates CSR for provided organization and organizational unit func createCSR(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, org, ou string) (*ecdsa.PublicKey, *x509.CertificateRequest, *big.Int) { pubKey, pkcs11Key := generateKeyPair(ctx, sess) diff --git a/internal/peer/common/common.go b/internal/peer/common/common.go index caae550247f..192d828fa7e 100644 --- a/internal/peer/common/common.go +++ b/internal/peer/common/common.go @@ -12,6 +12,7 @@ import ( "fmt" "io/ioutil" "os" + "strconv" "strings" "time" @@ -133,6 +134,7 @@ func InitCrypto(mspMgrConfigDir, localMSPID, localMSPType string) error { // Init the BCCSP SetBCCSPKeystorePath() + bccspConfig := factory.GetDefaultOpts() if config := viper.Get("peer.BCCSP"); config != nil { err = mapstructure.WeakDecode(config, bccspConfig) @@ -141,6 +143,10 @@ func InitCrypto(mspMgrConfigDir, localMSPID, localMSPType string) error { } } + if err := SetBCCSPConfigOverrides(bccspConfig); err != nil { + return err + } + err = mspmgmt.LoadLocalMspWithType(mspMgrConfigDir, bccspConfig, localMSPID, localMSPType) if err != nil { return errors.WithMessagef(err, "error when setting up MSP of type %s from directory %s", localMSPType, mspMgrConfigDir) @@ -149,6 +155,41 @@ func InitCrypto(mspMgrConfigDir, localMSPID, localMSPType string) error { return nil } +// Overrides BCCSP config values when corresponding environment variables +// are set. +func SetBCCSPConfigOverrides(bccspConfig *factory.FactoryOpts) error { + if pkcs11Default, exist := os.LookupEnv("CORE_PEER_BCCSP_DEFAULT"); exist { + bccspConfig.ProviderName = pkcs11Default + } + + // PKCS11 Overrides + if pkcs11Hash, exist := os.LookupEnv("CORE_PEER_BCCSP_PKCS11_HASH"); exist { + bccspConfig.Pkcs11Opts.HashFamily = pkcs11Hash + } + + if pkcs11Security, exist := os.LookupEnv("CORE_PEER_BCCSP_PKCS11_SECURITY"); exist { + pkcs11Sec, err := strconv.Atoi(pkcs11Security) + if err != nil { + return errors.Errorf("CORE_PEER_BCCSP_PKCS11_SECURITY set to non-integer value: %s", pkcs11Security) + } + bccspConfig.Pkcs11Opts.SecLevel = pkcs11Sec + } + + if pkcs11Library, exist := os.LookupEnv("CORE_PEER_BCCSP_PKCS11_LIBRARY"); exist { + bccspConfig.Pkcs11Opts.Library = pkcs11Library + } + + if pkcs11Label, exist := os.LookupEnv("CORE_PEER_BCCSP_PKCS11_LABEL"); exist { + bccspConfig.Pkcs11Opts.Label = pkcs11Label + } + + if pkcs11Pin, exist := os.LookupEnv("CORE_PEER_BCCSP_PKCS11_PIN"); exist { + bccspConfig.Pkcs11Opts.Pin = pkcs11Pin + } + + return nil +} + // SetBCCSPKeystorePath sets the file keystore path for the SW BCCSP provider // to an absolute path relative to the config file func SetBCCSPKeystorePath() { diff --git a/internal/peer/common/common_test.go b/internal/peer/common/common_test.go index 37842be1d32..44ce147b5b9 100644 --- a/internal/peer/common/common_test.go +++ b/internal/peer/common/common_test.go @@ -12,9 +12,12 @@ import ( "os" "path" "path/filepath" + "strconv" "strings" "testing" + "github.com/hyperledger/fabric/bccsp/factory" + "github.com/hyperledger/fabric/bccsp/pkcs11" "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/config/configtest" @@ -247,3 +250,57 @@ func TestInitCmdWithoutInitCrypto(t *testing.T) { common.InitCmd(packageCmd, nil) } + +func TestSetBCCSPConfigOverrides(t *testing.T) { + bccspConfig := factory.GetDefaultOpts() + envConfig := &factory.FactoryOpts{ + ProviderName: "test-default", + SwOpts: &factory.SwOpts{ + HashFamily: "SHA2", + SecLevel: 256, + Ephemeral: true, + }, + Pkcs11Opts: &pkcs11.PKCS11Opts{ + HashFamily: "test-pkcs11-hash", + SecLevel: 12345, + Library: "test-pkcs11-library", + Label: "test-pkcs11-label", + Pin: "test-pkcs11-pin", + }, + } + + t.Run("success", func(t *testing.T) { + cleanup := setBCCSPEnvVariables(envConfig) + defer cleanup() + err := common.SetBCCSPConfigOverrides(bccspConfig) + assert.NoError(t, err) + assert.Equal(t, envConfig, bccspConfig) + }) + + t.Run("PKCS11 security set to string value", func(t *testing.T) { + cleanup := setBCCSPEnvVariables(envConfig) + defer cleanup() + os.Setenv("CORE_PEER_BCCSP_PKCS11_SECURITY", "INSECURITY") + + err := common.SetBCCSPConfigOverrides(bccspConfig) + assert.EqualError(t, err, "CORE_PEER_BCCSP_PKCS11_SECURITY set to non-integer value: INSECURITY") + }) +} + +func setBCCSPEnvVariables(bccspConfig *factory.FactoryOpts) (cleanup func()) { + os.Setenv("CORE_PEER_BCCSP_DEFAULT", bccspConfig.ProviderName) + os.Setenv("CORE_PEER_BCCSP_PKCS11_SECURITY", strconv.Itoa(bccspConfig.Pkcs11Opts.SecLevel)) + os.Setenv("CORE_PEER_BCCSP_PKCS11_HASH", bccspConfig.Pkcs11Opts.HashFamily) + os.Setenv("CORE_PEER_BCCSP_PKCS11_PIN", bccspConfig.Pkcs11Opts.Pin) + os.Setenv("CORE_PEER_BCCSP_PKCS11_LABEL", bccspConfig.Pkcs11Opts.Label) + os.Setenv("CORE_PEER_BCCSP_PKCS11_LIBRARY", bccspConfig.Pkcs11Opts.Library) + + return func() { + os.Unsetenv("CORE_PEER_BCCSP_DEFAULT") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_SECURITY") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_HASH") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_PIN") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_LABEL") + os.Unsetenv("CORE_PEER_BCCSP_PKCS11_LIBRARY") + } +}