예제 #1
0
// Deploy deploys the supplied chaincode image to the validators through a transaction
func (d *Devops) Deploy(ctx context.Context, spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) {
	// get the deployment spec
	chaincodeDeploymentSpec, err := d.getChaincodeBytes(ctx, spec)

	if err != nil {
		devopsLogger.Error(fmt.Sprintf("Error deploying chaincode spec: %v\n\n error: %s", spec, err))
		return nil, err
	}

	// Now create the Transactions message and send to Peer.

	transID := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name

	var tx *pb.Transaction
	var sec crypto.Client

	if viper.GetBool("security.enabled") {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Initializing secure devops using context %s", spec.SecureContext)
		}
		sec, err = crypto.InitClient(spec.SecureContext, nil)
		defer crypto.CloseClient(sec)

		// remove the security context since we are no longer need it down stream
		spec.SecureContext = ""

		if nil != err {
			return nil, err
		}

		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating secure transaction %s", transID)
		}
		tx, err = sec.NewChaincodeDeployTransaction(chaincodeDeploymentSpec, transID)
		if nil != err {
			return nil, err
		}
	} else {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating deployment transaction (%s)", transID)
		}
		tx, err = pb.NewChaincodeDeployTransaction(chaincodeDeploymentSpec, transID)
		if err != nil {
			return nil, fmt.Errorf("Error deploying chaincode: %s ", err)
		}
	}

	if devopsLogger.IsEnabledFor(logging.DEBUG) {
		devopsLogger.Debug("Sending deploy transaction (%s) to validator", tx.Uuid)
	}
	resp := d.coord.ExecuteTransaction(tx)
	if resp.Status == pb.Response_FAILURE {
		err = fmt.Errorf(string(resp.Msg))
	}

	return chaincodeDeploymentSpec, err
}
예제 #2
0
func (d *Devops) invokeOrQuery(ctx context.Context, chaincodeInvocationSpec *pb.ChaincodeInvocationSpec, invoke bool) (*pb.Response, error) {

	if chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name == "" {
		return nil, fmt.Errorf("name not given for invoke/query")
	}

	// Now create the Transactions message and send to Peer.
	uuid, uuidErr := util.GenerateUUID()
	if uuidErr != nil {
		devopsLogger.Error(fmt.Sprintf("Error generating UUID: %s", uuidErr))
		return nil, uuidErr
	}
	var transaction *pb.Transaction
	var err error
	var sec crypto.Client
	if viper.GetBool("security.enabled") {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Initializing secure devops using context %s", chaincodeInvocationSpec.ChaincodeSpec.SecureContext)
		}
		sec, err = crypto.InitClient(chaincodeInvocationSpec.ChaincodeSpec.SecureContext, nil)
		defer crypto.CloseClient(sec)
		// remove the security context since we are no longer need it down stream
		chaincodeInvocationSpec.ChaincodeSpec.SecureContext = ""
		if nil != err {
			return nil, err
		}
	}
	transaction, err = d.createExecTx(chaincodeInvocationSpec, uuid, invoke, sec)
	if err != nil {
		return nil, err
	}
	if devopsLogger.IsEnabledFor(logging.DEBUG) {
		devopsLogger.Debug("Sending invocation transaction (%s) to validator", transaction.Uuid)
	}
	resp := d.coord.ExecuteTransaction(transaction)
	if resp.Status == pb.Response_FAILURE {
		err = fmt.Errorf(string(resp.Msg))
	} else {
		if !invoke && nil != sec && viper.GetBool("security.privacy") {
			if resp.Msg, err = sec.DecryptQueryResult(transaction, resp.Msg); nil != err {
				devopsLogger.Debug("Failed decrypting query transaction result %s", string(resp.Msg[:]))
				//resp = &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(err.Error())}
			}
		}
	}
	return resp, err
}
예제 #3
0
func (d *Devops) createExecTx(spec *pb.ChaincodeInvocationSpec, uuid string, invokeTx bool) (*pb.Transaction, error) {
	var tx *pb.Transaction
	var err error
	if viper.GetBool("security.enabled") {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Initializing secure devops using context %s", spec.ChaincodeSpec.SecureContext)
		}
		sec, err := crypto.InitClient(spec.ChaincodeSpec.SecureContext, nil)
		defer crypto.CloseClient(sec)

		// remove the security context since we are no longer need it down stream
		spec.ChaincodeSpec.SecureContext = ""

		if nil != err {
			return nil, err
		}
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating secure invocation transaction %s", uuid)
		}
		if invokeTx {
			tx, err = sec.NewChaincodeExecute(spec, uuid)
		} else {
			tx, err = sec.NewChaincodeQuery(spec, uuid)
		}
		if nil != err {
			return nil, err
		}
	} else {
		if devopsLogger.IsEnabledFor(logging.DEBUG) {
			devopsLogger.Debug("Creating invocation transaction (%s)", uuid)
		}
		var t pb.Transaction_Type
		if invokeTx {
			t = pb.Transaction_CHAINCODE_EXECUTE
		} else {
			t = pb.Transaction_CHAINCODE_QUERY
		}
		tx, err = pb.NewChaincodeExecute(spec, uuid, t)
		if nil != err {
			return nil, err
		}
	}
	return tx, nil
}
예제 #4
0
// GetEnrollmentCert retrieves the enrollment certificate for a given user.
func (s *ServerOpenchainREST) GetEnrollmentCert(rw web.ResponseWriter, req *web.Request) {
	// Parse out the user enrollment ID
	enrollmentID := req.PathParams["id"]

	if restLogger.IsEnabledFor(logging.DEBUG) {
		restLogger.Debug("REST received enrollment certificate retrieval request for registrationID '%s'", enrollmentID)
	}

	// If security is enabled, initialize the crypto client
	if viper.GetBool("security.enabled") {
		if restLogger.IsEnabledFor(logging.DEBUG) {
			restLogger.Debug("Initializing secure client using context '%s'", enrollmentID)
		}

		// Initialize the security client
		sec, err := crypto.InitClient(enrollmentID, nil)
		if err != nil {
			rw.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(rw, "{\"Error\": \"%s\"}", err)
			restLogger.Error(fmt.Sprintf("{\"Error\": \"%s\"}", err))

			return
		}

		// Obtain the client CertificateHandler
		handler, err := sec.GetEnrollmentCertificateHandler()
		if err != nil {
			rw.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(rw, "{\"Error\": \"%s\"}", err)
			restLogger.Error(fmt.Sprintf("{\"Error\": \"%s\"}", err))

			return
		}

		// Certificate handler can not be hil
		if handler == nil {
			rw.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(rw, "{\"Error\": \"Error retrieving certificate handler.\"}")
			restLogger.Error("{\"Error\": \"Error retrieving certificate handler.\"}")

			return
		}

		// Obtain the DER encoded certificate
		certDER := handler.GetCertificate()

		// Confirm the retrieved enrollment certificate is not nil
		if certDER == nil {
			rw.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(rw, "{\"Error\": \"Enrollment certificate is nil.\"}")
			restLogger.Error("{\"Error\": \"Enrollment certificate is nil.\"}")

			return
		}

		// Confirm the retrieved enrollment certificate has non-zero length
		if len(certDER) == 0 {
			rw.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintf(rw, "{\"Error\": \"Enrollment certificate length is 0.\"}")
			restLogger.Error("{\"Error\": \"Enrollment certificate length is 0.\"}")

			return
		}

		// Transforms the DER encoded certificate to a PEM encoded certificate
		certPEM := utils.DERCertToPEM(certDER)

		// As the enrollment certifiacate contains \n characters, url encode it before outputting
		urlEncodedCert := url.QueryEscape(string(certPEM))

		// Close the security client
		crypto.CloseClient(sec)

		rw.WriteHeader(http.StatusOK)
		fmt.Fprintf(rw, "{\"OK\": \"%s\"}", urlEncodedCert)
		if restLogger.IsEnabledFor(logging.DEBUG) {
			restLogger.Debug("Sucessfully retrieved enrollment certificate for secure context '%s'", enrollmentID)
		}
	} else {
		// Security must be enabled to request enrollment certificates
		rw.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(rw, "{\"Error\": \"Security functionality must be enabled before requesting client certificates.\"}")
		restLogger.Error("{\"Error\": \"Security functionality must be enabled before requesting client certificates.\"}")

		return
	}
}