diff --git a/hyperledger-fabric-network/HLF Enterprise Blockchain Integration with Greenstand Treetracker.md b/hyperledger-fabric-network/HLF Enterprise Blockchain Integration with Greenstand Treetracker.md new file mode 100644 index 0000000..53bffec --- /dev/null +++ b/hyperledger-fabric-network/HLF Enterprise Blockchain Integration with Greenstand Treetracker.md @@ -0,0 +1,240 @@ +# Enterprise Blockchain (Hyperledger Fabric) Integration with Greenstand Treetracker Platform + +## Introduction + +Greenstand’s Treetracker project connects people and communities planting trees around the world with donors and investors. Growers use the mobile app to take geotagged photos of each tree, and these captures are uploaded to a verification platform ([greenstand.org](https://greenstand.org)). Once a tree is verified, its Impact Token can be traded; donors and investors can purchase tokens directly from growers, providing income and incentives for reforestation ([greenstand.org](https://greenstand.org)). This system demands transparency and trust: donors must be certain that each token reflects a verified tree, and growers need assurance that their contributions and rewards are accurately recorded. To meet these requirements, Greenstand is exploring an enterprise blockchain solution based on Hyperledger Fabric (HLF). + +Hyperledger Fabric is an open-source, permissioned blockchain platform built for business applications. Unlike permissionless networks, Fabric uses deterministic consensus and membership services to ensure that only authorised participants transact and that their transactions cannot be altered ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Fabric’s modular architecture supports pluggable consensus algorithms, private communication channels, and rich programming models for smart contracts. This documentation explains how Hyperledger Fabric can be integrated with the Treetracker system and provides guidance for a production-ready deployment. + +--- + +## Hyperledger Fabric Overview + +### Permissioned and Modular Design + +In Hyperledger Fabric, every actor—peers, orderers, client applications and administrators—possesses a digital identity encapsulated in an X.509 certificate ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Identities are issued by trusted Certificate Authorities (CAs) and form the basis for a Membership Service Provider (MSP) which determines who may read, write or configure data ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). The platform separates the execution of smart contracts (chaincode), transaction ordering and validation, improving performance and allowing organisations to plug in different components as needed ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +**Key features of Hyperledger Fabric include:** + +- **Deterministic consensus:** Fabric’s ordering service uses deterministic algorithms rather than probabilistic mechanisms. A block validated by a peer is guaranteed to be final and correct, preventing forks ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Private communication channels:** A channel is a private subnet of communication among specific organisations; each channel has its own ledger, smart contracts and policies ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Channels allow competitors to coexist on the same network while keeping sensitive data isolated ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Smart contracts (chaincode):** Business logic is encapsulated in chaincode, which endorsing peers execute to produce a read/write set; the endorsement policy specifies which peers must sign a transaction ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **State database:** Peers maintain a world state and a blockchain. The world state stores current values of ledger states, while the blockchain stores the history of transactions. Once transactions are appended to the blockchain, they cannot be modified ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Pluggable databases:** Fabric supports LevelDB (embedded key-value store) and CouchDB (external document database). CouchDB enables JSON queries and indexing but requires extra setup ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +### Consensus and Ordering Service + +Fabric’s ordering service packages endorsed transactions into blocks, determines their order and delivers them to peers. The recommended implementation is **Raft**, a crash-fault-tolerant (CFT) consensus algorithm introduced in Fabric 1.4.1 ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Raft uses a leader–follower model: a leader is elected per channel and replicates transactions to follower orderers ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). If a leader fails, a new leader is elected, and the system continues as long as a quorum (a majority of orderer nodes) remains ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). In production, organisations typically deploy three or five orderer nodes across different data centres to ensure high availability ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +--- + +## Treetracker Integration Architecture +HLF TT Arch2 + +### Client Applications + +- **Mobile Treetracker App:** A application for growers. It allows users to capture a tree’s photo and location, compute the image’s hash, and submit this data to the blockchain. +- **Web Map Interface:** A Next.js web app that displays verified trees using data from the blockchain and an off-chain database. +- **Admin Panel:** A React dashboard that lets authorised verifiers review tree submissions and update their status. +- **Wallet Application:** A user interface where Impact Tokens can be viewed, transferred or traded. + +### API Gateway and Supporting Services + +- **HLF Gateway Service:** A Node.js (or TypeScript) service that acts as the client interface to Fabric. It uses the Fabric Gateway API, which simplifies transaction processing by handling endorsement collection and submission to the orderer ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). The gateway performs functions like evaluating a transaction (read-only query), collecting endorsements, submitting transactions and waiting for commit status ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Identity Management:** Integration with Fabric CA for user registration, enrollment and certificate issuance. Users authenticate via a separate identity provider (e.g., Keycloak) and receive X.509 certificates for blockchain access. Fabric CAs support registration of identities, issuance of enrolment certificates, renewal and revocation ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). + +- **Off-chain Database:** PostgreSQL is used to store metadata (tree attributes, user profiles), image hashes and query-optimised views. Sensitive data remains off-chain; only hashes and references are stored on the blockchain. CouchDB is used as the state database on peers for queryable JSON storage ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Event Listeners:** Microservices subscribe to block and chaincode events through the Fabric gateway. When a tree is verified, they update the off-chain database and trigger token minting. + +### Security and Compliance + +- **TLS/mTLS Encryption:** The Fabric CA documentation emphasises enabling TLS for the CA server; without TLS, the CA is vulnerable to network attacks ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). Similarly, all peer-to-peer and client-peer communications should use TLS and, where appropriate, mutual TLS for authentication. + +- **Hardware Security Modules (HSMs):** Private keys for orderers, peers and gateway clients should be stored in HSMs or soft HSMs. Fabric CA can be configured to use external HSMs ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). + +- **Audit Logging:** The immutable blockchain ledger records every transaction. The ledger is comprised of a blockchain (immutable sequence of blocks) and a world state; once a transaction is appended to the blockchain, it cannot be altered ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). This immutable audit trail satisfies regulatory requirements. + +- **GDPR and Data Privacy:** Sensitive data is kept off-chain in PostgreSQL, while hashed references are stored on-chain. Private data collections may specify a `blockToLive` property to purge private data after a certain number of blocks, enabling data expiry to support right-to-be-forgotten requirements ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +--- + +## Hyperledger Fabric Network Setup +HLF TT Arch3 + +### Ordering Service + +A **Raft** ordering service is provisioned with five orderer nodes, distributed across multiple data centres for high availability. Raft is crash-fault-tolerant; it can withstand the loss of up to two nodes in a five-node cluster ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Each channel runs its own Raft instance, electing a leader per channel ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Organisations may specify which of their orderer nodes participate in each channel ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +### Peers + +Each organisation runs endorsing and committing peers. Endorsing peers execute chaincode and produce proposal responses; committing peers validate transactions and update their ledgers. Peers use a **gossip** protocol to discover other peers, disseminate blocks and private data, and keep ledgers consistent ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Gossip also elects leaders within organisations to efficiently pull blocks from the ordering service ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +### Channels +HLF TT Arch4 2 + +Treetracker uses several channels: + +- **Public Channel:** Contains tree registration, verification and token transfer data. All participating organisations—Greenstand, CBOs, investors and verifiers—have access. Each organisation designates **anchor peers** to communicate with peers in other organisations. A channel is a private subnet where all transactions are confidential among its members ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Private Channels:** Used for sensitive organisational data, e.g., investor commitments or verification notes. Only authorised organisations join these channels. + +- **Cross-Channel Transactions:** For multi-organisation interactions, Fabric supports cross-channel data referencing (private data cross-channel flows require careful endorsement policies). + +### Certificate Authorities and Identity + +For each organisation, a root CA issues certificates for one or more intermediate CAs. Intermediate CAs issue X.509 certificates to users, peers and orderers. The Fabric CA server is initialised with a CSR (Certificate Signing Request) specifying fields like Common Name (CN), organisation (O), organisational unit (OU), location (L), state (ST) and country (C) ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). The server can generate a self-signed CA certificate or obtain a certificate signed by a parent CA ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). TLS is enabled to secure enrolment and registration ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). The Membership Service Provider (MSP) uses these certificates to define valid identities and assign roles ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +### Smart Contracts (Chaincode) +HLF TT Arch5 + +Chaincode encapsulates the business logic of Treetracker. Four main contracts are envisaged: + +- **TreeContract:** Functions to register a tree, update its status, verify tree data and query history. For example, the `RegisterTree` function validates input parameters, checks that the tree does not already exist, creates a tree asset and stores it on the ledger. The chaincode then returns an error if the tree ID is empty or already exists, and updates the ledger state accordingly. Smart contracts should perform thorough input validation and avoid duplicate IDs ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **TokenContract:** Handles the creation (minting), transfer and burning of Impact Tokens. Tokens are minted once a tree is verified, linking a token’s ownership to a specific tree ID in the ledger. + +- **UserContract:** Manages user registration, profile updates and permission grants. User attributes (roles, organisation) are stored off-chain but referenced in the ledger for auditability. + +- **AuditContract:** Logs transactions, creates audit trails and performs compliance checks. Each log entry contains a transaction ID, actor identity, action, resource ID and timestamp. + +Chaincode runs in a Docker container managed by peers. Fabric’s **new chaincode lifecycle** involves packaging, installing, approving and committing chaincode definitions. An endorsement policy—such as requiring Greenstand and Verifier peers to sign tree verifications—is defined when committing the chaincode ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +--- + +## Transaction Flow Mapping +HLF TT Arch6 + +A typical tree registration and token issuance flow maps onto Fabric’s transaction flow ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)): + +1. **Tree Capture:** A grower uses the mobile app to capture a photo and GPS coordinates. The app hashes the image and sends a transaction proposal to the Fabric gateway. + +2. **Proposal Evaluation:** The gateway selects endorsing peers and forwards the proposal. The endorsing peers validate the proposal’s structure, ensure it has not been submitted before and that the submitter is authorised ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Each peer executes the `RegisterTree` function, producing a read/write set but not updating the ledger. ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +3. **Endorsement Collection:** Endorsing peers sign the proposal response. The gateway verifies that all responses match and assembles a transaction ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +4. **Ordering:** The transaction is sent to the ordering service, which orders transactions into blocks. In Raft, the ordering node routes the transaction to the current leader for that channel; the leader replicates the log entry to followers ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Once a majority of orderers (a quorum) agree on the block, it is committed and distributed ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +5. **Validation and Commit:** Each committing peer receives the block, verifies that the endorsement policy is satisfied and checks for any read/write conflicts ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Valid transactions are committed to the ledger and the world state is updated; invalid transactions are tagged accordingly ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). A commit event is emitted to notify the application. + +6. **Token Minting:** An event listener service detects the tree verification transaction and invokes the `MintImpactToken` function on the TokenContract, creating tokens for the grower. The updated token balance is stored on the ledger and synchronised with the off-chain wallet application. + +--- + +## Private Data and Confidentiality + +Greenstand’s blockchain must protect sensitive data (e.g., precise GPS coordinates or personal data) while keeping proof of environmental impact accessible. Hyperledger Fabric addresses this through **private data collections**. A private data collection is defined in the chaincode definition and specifies which organisations are allowed to access the data ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Properties include: + +- **policy:** A Signature policy listing organisations permitted to store the data ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **requiredPeerCount / maxPeerCount:** Minimum and maximum numbers of peers to disseminate data to at endorsement time, ensuring redundancy ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **blockToLive:** Number of blocks after which private data is purged from peers; a value of `0` retains data indefinitely ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **memberOnlyRead / memberOnlyWrite:** Flags restricting read/write access to collection members ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +During tree registration, only a **hash** of the image and location is written to the public ledger. The actual image and precise location remain **off-chain**, and the private data collection stores the hash and metadata accessible only to authorised organisations. + +--- + +## Data Dissemination and Gossip + +Hyperledger Fabric implements a **gossip protocol** to disseminate ledger data and maintain consistency across peers. Each peer gossips messages to a random subset of peers, ensuring scalable and reliable distribution ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Gossip performs the following functions ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)): + +- **Peer discovery and membership management** — peers continually identify available peers and detect offline peers. +- **Private data dissemination** — endorsing peers disseminate private data to authorised peers in the collection. +- **Block dissemination** — leader peers pull blocks from the ordering service and optionally gossip them to peers within their organisation ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). +- **State transfer** — new peers can pull blocks from other peers to catch up to the latest ledger height. + +Leader election within an organisation may be static or dynamic. **Static leader election** designates specific peers as leaders; **dynamic leader election** allows peers to elect a leader based on heartbeat messages ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). This mechanism ensures efficient ordering-service bandwidth usage and high availability. + +--- + +## Off-Chain Data and Database Integration + +Hyperledger Fabric’s world state stores only key–value data. For Treetracker, large assets such as images, high-resolution GPS data and complex queries require an external database. The integration uses: + +- **PostgreSQL** for tree metadata, user profiles, tokens and audit logs. It supports rich queries, analytics and compliance requirements. + +- **CouchDB** as the peer’s state database. CouchDB allows storage of JSON documents and supports JSON queries and indexing ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). JSON data modelling enables chaincode to query the ledger using selectors like + `{ "selector": {"docType":"asset","owner": } }` + ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). It is recommended to model data as JSON for auditing and reporting ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +Off-chain data and on-chain hashes must be synchronised via **event listeners**. The event listener reads block events, extracts transaction data and updates the PostgreSQL database. The database can store indices for fast lookup (e.g., by grower or species) and support GIS queries for mapping. + +--- + +## Identity and Access Control + +### Digital Certificates and MSPs + +Every actor in a Fabric network has a digital identity in the form of an X.509 certificate ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). These certificates are issued by a hierarchy of CAs, starting with a root CA, then intermediate CAs for each organisation. When the CA server is initialised, a self-signed certificate or a certificate signed by a parent CA is generated ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). The certificate’s subject contains fields such as Common Name (CN), Organisation (O) and location ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). The MSP defines the rules for valid identities and maps attributes to roles ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +### TLS and Mutual TLS + +TLS must be enabled on the CA server and between all network components ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). For stronger security, **mutual TLS** can be configured so that clients present certificates during communication, ensuring both ends of the channel are authenticated. Orderers and peers should use TLS certificates signed by a trusted CA. + +### Role-Based Access Control (RBAC) + +Fabric chaincode can inspect client identities and attributes. Applications may embed attributes (e.g., `role=verifier` or `role=grower`) into X.509 certificates or use external identity providers such as Keycloak. Chaincode functions can call the `GetClientIdentity().GetAttributeValue()` API to enforce RBAC. Endorsement policies at chaincode or collection level ensure that only specific organisations can approve a transaction ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +--- + +## Auditability and Compliance + +The immutable blockchain ensures that every transaction, from tree registration to token transfer, is permanently recorded. The ledger comprises a **world state** (current values) and a **blockchain** (transaction history). While the world state can change, the blockchain history cannot be modified ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). This property provides an indisputable audit trail for environmental credits and token trades. Organisations can implement further audit services: an **AuditContract** logs additional context such as user IDs, client applications and compliance checks. + +To meet **GDPR** requirements, private data collections allow data to be purged after a specified number of blocks ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Sensitive off-chain data can also be deleted from PostgreSQL while keeping the on-chain hash, preserving proof without exposing personal data. + +--- + +## Benefits of HLF Integration for Treetracker + +- **Transparency and Trust:** Channels provide shared, immutable ledgers accessible to authorised participants. The ledger stores the current state and the full history of transactions, making tree planting and token transfers transparent and traceable ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Performance and Scalability:** Separating transaction execution, ordering and validation allows Fabric to process many transactions concurrently ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Raft consensus scales horizontally; adding more orderer nodes increases throughput while maintaining finality ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +- **Interoperability:** Standard APIs (Fabric Gateway) and SDKs in Go, Node/TypeScript and Java simplify application development ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Off-chain databases and event listeners integrate easily with existing systems, such as payment platforms or carbon credit marketplaces. + +- **Privacy and Confidentiality:** Private data collections restrict data access to authorised organisations, while still allowing participation in shared channels ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Off-chain storage and hashing protect sensitive personal or location data. + +- **Auditability and Compliance:** The immutable ledger and world state create verifiable, tamper-resistant records ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Audit contracts and event listeners can generate reports and support regulatory audits. + +- **Cost Efficiency:** By removing intermediaries and automating verification, Fabric reduces transaction costs. Growers and investors transact directly via smart contracts, while sponsors can trace the environmental impact of their contributions. + +--- + +## Implementation Guidance + +To deploy the Treetracker blockchain solution, organisations should follow these steps: + +1. **Set up Certificate Authorities:** Deploy a root CA and intermediate CAs for each organisation. Initialise the CA server with a CSR specifying the subject fields ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). Enable TLS on the CA server ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). + +2. **Generate Identities:** Register and enrol peers, orderers and users via the CA. Create MSP folders containing the certificates and keys for each component. Use HSMs where possible ([hyperledger-fabric-ca.readthedocs.io](https://hyperledger-fabric-ca.readthedocs.io)). + +3. **Configure Ordering Service:** Create a Raft consortium with an odd number of orderer nodes (3 or 5). Configure the `orderer.yaml` file; specify `ConsensusType: etcdraft`, enable TLS, and define the consenter set. Deploy orderers across data centres for fault tolerance ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +4. **Deploy Peers:** Deploy endorsing and committing peers per organisation. Configure the gossip protocol and set anchor peers. Choose CouchDB as the state database for advanced queries ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). Enable TLS and configure static or dynamic leader election ([hyperledger-fabric.readthedocs.io](https://hyperledger-fabric.readthedocs.io)). + +5. **Create Channels:** Generate channel configuration transactions (`configtx.yaml`) specifying member organisations, anchor peers and policies. Use a public channel for tree registration and token transfers, and additional channels for sensitive data. Set channel capabilities to the latest Fabric version. + +6. **Package and Deploy Chaincode:** Write chaincode for the TreeContract, TokenContract, UserContract and AuditContract. Package and install chaincode on endorsing peers. Organisations approve and commit the chaincode definition with an endorsement policy reflecting the required signatories (e.g., both Greenstand and Verifier must endorse a tree verification). Use private data collections for sensitive fields. + +7. **Set up API Gateway and Event Listeners:** Implement a Node.js/TypeScript gateway service using the Fabric Gateway SDK. The gateway should manage wallet identities and map external authentication (e.g., JWT tokens) to Fabric identities. Event listener services should subscribe to block and chaincode events and update the off-chain database. + +8. **Integrate Off-Chain Database and Storage:** Deploy PostgreSQL for metadata and MinIO/S3 for images. Ensure that image hashes stored on-chain match the stored files. Implement scheduled tasks for data purging as required by GDPR. + +9. **Implement Client Applications:** Enhance the mobile app to compute image hashes and handle offline submission with retries. Build the admin panel for reviewers and the wallet app for token management. Use the web map to display verified trees by querying the off-chain database and cross-checking the blockchain state. + +10. **Monitor and Secure the Network:** Use Prometheus and Grafana to monitor peer and orderer health, transaction latency and block height. Configure alerting for quorum loss, leader changes and endorsement failures. Conduct regular audits of identities and MSP configurations. + +--- + +## Conclusion + +By integrating Hyperledger Fabric with Greenstand’s Treetracker system, growers, donors and investors gain a transparent, trustworthy and scalable platform for environmental impact tracking. The permissioned blockchain records every tree capture, verification and token transfer in an immutable ledger, while private data collections and off-chain databases protect sensitive information. Raft consensus ensures high availability and fault tolerance, and the Fabric Gateway simplifies client application development. With proper configuration, robust identity management and thorough monitoring, this architecture can deliver a resilient enterprise blockchain solution that aligns economic incentives with ecological restoration. diff --git a/hyperledger-fabric-network/README.md b/hyperledger-fabric-network/README.md new file mode 100644 index 0000000..46a9387 --- /dev/null +++ b/hyperledger-fabric-network/README.md @@ -0,0 +1,319 @@ +Treetracker HLF Network + +
+

🌳 Blockchain-based Tree Tracking Network 🌳

+

A production-ready Hyperledger Fabric network for transparent tree planting and carbon offset tracking

+
+ +[![Hyperledger Fabric](https://img.shields.io/badge/Hyperledger%20Fabric-2.5.7-blue.svg)](https://hyperledger-fabric.readthedocs.io/) +[![Kubernetes](https://img.shields.io/badge/Kubernetes-1.28+-blue.svg)](https://kubernetes.io/) +[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) +[![Network Status](https://img.shields.io/badge/Network-Production%20Ready-brightgreen.svg)](#) + +--- + +## 🌍 Overview + +The Hyperledger Fabric Treetracker Network is a blockchain-based solution designed to provide transparent, immutable tracking of tree planting initiatives and carbon offset programs. Built for [Greenstand](https://greenstand.org/) and partners, this network ensures accountability in environmental restoration projects through distributed ledger technology. + +### Key Features + +- **🔒 Immutable Tree Records** - Every tree planting event is permanently recorded on the blockchain +- **🤝 Multi-Organization Network** - Supports Greenstand, CBOs, Investors, and Verifiers +- **🌐 Public Transparency** - All stakeholders can verify tree planting data +- **📊 Real-time Analytics** - Live dashboards for monitoring forest restoration progress +- **🔐 Enterprise Security** - Certificate-based authentication and TLS encryption +- **📈 Scalable Infrastructure** - Kubernetes-based deployment supporting global operations + +--- + +## 🏗️ Network Architecture + +### Organizations + +| Organization | Role | Peers | Description | +|--------------|------|-------|-------------| +| **Greenstand** | Network Admin | 3 | Primary tree tracking organization | +| **CBO** | Tree Planters | 2 | Community-Based Organizations | +| **Investor** | Funders | 2 | Carbon offset purchasers | +| **Verifier** | Validators | 1 | Independent verification entities | + +### Network Components + +- **🏦 Ordering Service**: 5-node Raft consensus cluster +- **🔐 Certificate Authorities**: 5 CAs (1 Root + 4 Organization CAs) +- **📊 Monitoring**: Prometheus + Grafana stack +- **🗄️ Storage**: Persistent volumes with automatic backup +- **🌐 API Gateway**: RESTful APIs for external integration + +--- + +## 🚀 Quick Start + +### Prerequisites + +- **Kubernetes Cluster**: v1.23+ with 5+ nodes +- **Storage**: 500GB+ SSD with dynamic provisioning +- **Resources**: 32+ CPU cores, 64GB+ RAM +- **Network**: LoadBalancer support for external access + +### 1. Clone the Repository + +```bash +git clone https://github.com/Greenstand/hyperledger-fabric-network.git +cd hyperledger-fabric-network +``` + +### 2. Deploy the Network + +```bash +# Deploy complete network infrastructure +./scripts/deploy-treetracker-network.sh + +# Create channels +./scripts/create-channels.sh + +# Deploy chaincode +./scripts/deploy-chaincode.sh + +# Verify deployment +./scripts/test-network.sh +``` + +### 3. Access the Network + +```bash +# Get network status +kubectl get pods --all-namespaces | grep hlf- + +# Access API Gateway +kubectl port-forward svc/api-gateway 8080:80 -n treetracker-apps + +# View monitoring dashboard +kubectl port-forward svc/grafana 3000:3000 -n monitoring +``` + +--- + +## 📚 Documentation + +Comprehensive documentation is available in the `/docs` directory: + +### For Users & Operators +- 📖 **[User Manual](docs/TREETRACKER_USER_MANUAL.md)** - Complete user guide for network operations +- 🛠️ **[Deployment Guide](docs/TREETRACKER_DEPLOYMENT_GUIDE.md)** - Step-by-step deployment instructions + +### For Developers +- 💻 **[Integration Manual](docs/TREETRACKER_INTEGRATION_MANUAL.md)** - SDK usage and API integration +- 🏗️ **[Architecture Guide](docs/TREETRACKER_ARCHITECTURE_GUIDE.md)** - Network design and component details + +### Quick Reference +- [API Documentation](docs/TREETRACKER_INTEGRATION_MANUAL.md#api-reference) +- [Chaincode Functions](docs/TREETRACKER_INTEGRATION_MANUAL.md#chaincode-development) +- [Troubleshooting Guide](docs/TREETRACKER_DEPLOYMENT_GUIDE.md#troubleshooting) +- [Monitoring & Alerts](docs/TREETRACKER_ARCHITECTURE_GUIDE.md#monitoring-and-observability) + +--- + +## 🌐 Network Endpoints + +### Production Network +- **API Gateway**: `https://api.treetracker.network` +- **Blockchain Explorer**: `https://explorer.treetracker.network` +- **Monitoring Dashboard**: `https://monitoring.treetracker.network` + +### Development Network +- **API Gateway**: `http://localhost:8080` +- **Grafana**: `http://localhost:3000` +- **Prometheus**: `http://localhost:9090` + +--- + +## 🔧 Directory Structure + +``` +hyperledger-fabric-network/ +├── 📁 chaincode/ # Smart contracts +│ └── treetracker/ # Tree tracking chaincode (Go) +├── 📁 config/ # Network configuration +│ ├── configtx.yaml # Channel configuration +│ ├── crypto-config.yaml # Certificate configuration +│ └── network-config.yaml # Main network settings +├── 📁 docs/ # Documentation +│ ├── TREETRACKER_USER_MANUAL.md +│ ├── TREETRACKER_INTEGRATION_MANUAL.md +│ ├── TREETRACKER_ARCHITECTURE_GUIDE.md +│ └── TREETRACKER_DEPLOYMENT_GUIDE.md +├── 📁 k8s/ # Kubernetes manifests +│ ├── ca/ # Certificate Authority deployments +│ ├── orderer/ # Orderer node deployments +│ ├── peers/ # Peer node deployments +│ └── monitoring/ # Monitoring stack +├── 📁 scripts/ # Deployment and management scripts +│ ├── deploy-treetracker-network.sh +│ ├── create-channels.sh +│ ├── deploy-chaincode.sh +│ └── test-network.sh +└── 📁 api/ # REST API gateway + ├── nodejs/ # Node.js SDK integration + └── gateway/ # API Gateway service +``` + +--- + +## 🔐 Security Features + +### Certificate Management +- **Root CA**: Self-signed root certificate authority +- **Organization CAs**: Individual CAs for each organization +- **TLS Encryption**: All network communication encrypted +- **Certificate Rotation**: Automated certificate lifecycle management + +### Network Security +- **RBAC**: Role-based access control for all operations +- **Network Policies**: Kubernetes network segmentation +- **Mutual TLS**: Peer-to-peer authentication +- **HSM Support**: Hardware security module integration (optional) + +### Data Privacy +- **Channel Isolation**: Private data channels between organizations +- **Endorsement Policies**: Multi-signature transaction validation +- **Audit Trails**: Immutable transaction logs +- **Data Encryption**: At-rest and in-transit encryption + +--- + +## 📊 Monitoring & Observability + +### Metrics Collection +- **Peer Metrics**: Transaction throughput, ledger size, endorsement latency +- **Orderer Metrics**: Block creation rate, consensus performance +- **Network Metrics**: Channel health, certificate status +- **Application Metrics**: API response times, chaincode execution + +### Alerting +- **Network Health**: Peer/orderer downtime alerts +- **Performance**: Transaction latency thresholds +- **Security**: Certificate expiration warnings +- **Capacity**: Storage and resource utilization + +### Dashboards +- **Executive Dashboard**: High-level KPIs and network status +- **Operations Dashboard**: Detailed technical metrics +- **Business Dashboard**: Tree planting progress and carbon metrics + +--- + +## 🧪 Testing & Quality Assurance + +### Test Coverage +- **Unit Tests**: Chaincode function testing +- **Integration Tests**: End-to-end network testing +- **Performance Tests**: Load testing and benchmarking +- **Security Tests**: Penetration testing and vulnerability scans + +### Continuous Integration +- **Automated Testing**: GitHub Actions CI/CD pipeline +- **Code Quality**: SonarQube analysis +- **Security Scanning**: Container and dependency scanning +- **Deployment Testing**: Automated deployment validation + +--- + +## 🚀 Deployment Options + +### Cloud Providers +- **AWS**: EKS with managed services +- **Google Cloud**: GKE with Cloud SQL +- **Azure**: AKS with Azure Storage +- **DigitalOcean**: DOKS with block storage + +### On-Premises +- **Bare Metal**: Direct Kubernetes installation +- **VMware**: vSphere with Tanzu +- **OpenShift**: Red Hat OpenShift platform + +### Development +- **Kind**: Local Kubernetes in Docker +- **Minikube**: Single-node local cluster +- **Docker Compose**: Simplified local development + +--- + +## 🤝 Contributing + +We welcome contributions from the community! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details. + +### Development Workflow +1. Fork the repository +2. Create a feature branch +3. Make your changes with tests +4. Submit a pull request + +### Code Standards +- **Go**: Follow Go best practices for chaincode +- **JavaScript**: ESLint configuration for API code +- **Documentation**: Update docs for any API changes +- **Testing**: Maintain 80%+ test coverage + +--- + +## 📞 Support & Community + +### Getting Help +- **Documentation**: Comprehensive guides in `/docs` +- **GitHub Issues**: Bug reports and feature requests +- **Discord**: Real-time community support +- **Email**: technical-support@greenstand.org + +### Community Resources +- **Greenstand Website**: [https://greenstand.org](https://greenstand.org) +- **Slack Channel**: [#treetracker-blockchain](https://greenstand.slack.com) +- **Developer Forum**: [https://forum.greenstand.org](https://forum.greenstand.org) + +--- + +## 📈 Roadmap + +### Current Release (v1.0) +- ✅ Multi-organization network +- ✅ Tree tracking chaincode +- ✅ Kubernetes deployment +- ✅ Monitoring and alerting + +### Next Release (v1.1) +- 🔄 Mobile wallet integration +- 🔄 Carbon credit tokenization +- 🔄 Enhanced analytics dashboard +- 🔄 Multi-chain interoperability + +### Future Releases +- 📋 IoT sensor integration +- 📋 Satellite imagery verification +- 📋 Machine learning analytics +- 📋 Cross-border payment rails + +--- + +## 📄 License + +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. + +--- + +## 🙏 Acknowledgments + +- **Hyperledger Foundation**: For the excellent Fabric framework +- **Greenstand Team**: For environmental vision and leadership +- **Open Source Community**: For tools, libraries, and inspiration +- **Tree Planting Partners**: CBOs worldwide making real impact + +--- + +**🌱 Together, we're growing a more transparent and sustainable future through blockchain technology! 🌱** + +
+ Architected with ❤️ by Imos Aikoroje For Greenstand Community
+ greenstand.org | + GitHub +
diff --git a/hyperledger-fabric-network/ca/DOCUMENTATION_INDEX.md b/hyperledger-fabric-network/ca/DOCUMENTATION_INDEX.md new file mode 100644 index 0000000..cbbe0c5 --- /dev/null +++ b/hyperledger-fabric-network/ca/DOCUMENTATION_INDEX.md @@ -0,0 +1,183 @@ +# CA Infrastructure Documentation Index + +## Document Overview + +This directory contains comprehensive documentation for the Hyperledger Fabric Certificate Authority infrastructure. The documentation is organized into several key areas covering different aspects of CA management and operations. + +## Documentation Structure + +### 📋 Core Documentation + +| Document | Purpose | Audience | Last Updated | +|----------|---------|----------|--------------| +| [`README.md`](README.md) | Overview and quick start guide | All users | 2024-09-02 | +| [`TECHNICAL_SPECS.md`](TECHNICAL_SPECS.md) | Technical specifications and architecture | Engineers, Architects | 2024-09-02 | +| [`OPERATIONAL_PROCEDURES.md`](OPERATIONAL_PROCEDURES.md) | Daily operations and maintenance | Operations Teams | 2024-09-02 | +| [`SECURITY_PROCEDURES.md`](SECURITY_PROCEDURES.md) | Security protocols and incident response | Security Teams | 2024-09-02 | + +### 📁 Directory Documentation + +| Component | Location | Documentation | +|-----------|----------|---------------| +| **Helm Charts** | `helm-charts/` | Individual chart README files | +| **Scripts** | `scripts/` | Script headers and inline documentation | +| **Fabric CA Configs** | `fabric-ca/` | Configuration file comments | +| **Certificate Monitor** | `../monitoring/` | Integration documentation | + +## Quick Reference Guide + +### 🚀 Getting Started + +**New to CA infrastructure?** +1. Start with [`README.md`](README.md) for overview and quick start +2. Review [`TECHNICAL_SPECS.md`](TECHNICAL_SPECS.md) for architecture understanding +3. Follow deployment procedures in scripts documentation + +**Operations team?** +1. Focus on [`OPERATIONAL_PROCEDURES.md`](OPERATIONAL_PROCEDURES.md) +2. Review daily/weekly/monthly procedures +3. Familiarize with troubleshooting procedures + +**Security team?** +1. Study [`SECURITY_PROCEDURES.md`](SECURITY_PROCEDURES.md) +2. Review incident response procedures +3. Understand compliance requirements + +### 🔍 Common Tasks + +| Task | Primary Document | Supporting Documents | +|------|------------------|---------------------| +| **Deploy new CA** | README.md | TECHNICAL_SPECS.md | +| **Certificate renewal** | OPERATIONAL_PROCEDURES.md | SECURITY_PROCEDURES.md | +| **Backup/restore** | OPERATIONAL_PROCEDURES.md | TECHNICAL_SPECS.md | +| **Incident response** | SECURITY_PROCEDURES.md | OPERATIONAL_PROCEDURES.md | +| **Performance tuning** | TECHNICAL_SPECS.md | OPERATIONAL_PROCEDURES.md | +| **Security hardening** | SECURITY_PROCEDURES.md | TECHNICAL_SPECS.md | + +## Document Contents Summary + +### [`README.md`](README.md) +- **Overview**: CA infrastructure introduction and architecture +- **Quick Start**: Step-by-step deployment guide +- **Directory Structure**: File and folder organization +- **Basic Operations**: Common commands and procedures +- **Troubleshooting**: Common issues and solutions +- **Integration**: How CA integrates with other systems + +### [`TECHNICAL_SPECS.md`](TECHNICAL_SPECS.md) +- **System Architecture**: Technical design and component relationships +- **Container Specifications**: Resource requirements and configurations +- **Network Configuration**: Security, ports, and communication +- **API Documentation**: REST APIs and CLI commands +- **Performance Metrics**: Scalability limits and capacity planning +- **Configuration Management**: Environment variables and ConfigMaps +- **Version Management**: Upgrade procedures and compatibility + +### [`OPERATIONAL_PROCEDURES.md`](OPERATIONAL_PROCEDURES.md) +- **Standard Operating Procedures**: Daily, weekly, monthly tasks +- **Incident Response**: Emergency procedures and escalation +- **Maintenance Procedures**: Planned maintenance and updates +- **Monitoring Procedures**: Health checks and performance monitoring +- **Backup/Restore**: Complete data protection procedures +- **Change Management**: Configuration and version changes + +### [`SECURITY_PROCEDURES.md`](SECURITY_PROCEDURES.md) +- **Security Framework**: Objectives and access control +- **Cryptographic Security**: Key management and certificate validation +- **Network Security**: Segmentation and TLS configuration +- **Incident Response**: Security incident classification and response +- **Compliance**: Audit procedures and regulatory requirements +- **Security Hardening**: Container and network security measures + +## Documentation Maintenance + +### 📝 Update Schedule + +| Document Type | Update Frequency | Trigger Events | +|---------------|------------------|----------------| +| **README.md** | Quarterly | Major feature additions, structural changes | +| **TECHNICAL_SPECS.md** | Bi-annually | Version upgrades, architecture changes | +| **OPERATIONAL_PROCEDURES.md** | Monthly | Process improvements, new procedures | +| **SECURITY_PROCEDURES.md** | Quarterly | Security policy changes, incident learnings | + +### ✍️ Contributing to Documentation + +#### Documentation Standards +- **Format**: Markdown with consistent styling +- **Code Blocks**: Include language identifiers and executable examples +- **Version Control**: All changes tracked in git +- **Review Process**: Technical review required for procedure changes + +#### Update Process +1. **Identify Changes**: Document what needs updating +2. **Draft Updates**: Create updated content following standards +3. **Technical Review**: Review for accuracy and completeness +4. **Security Review**: Security procedures require security team review +5. **Approval**: Platform lead approval for operational changes +6. **Deployment**: Update files and notify relevant teams + +### 🔄 Document Relationships + +```mermaid +graph LR + A[README.md] --> B[TECHNICAL_SPECS.md] + A --> C[OPERATIONAL_PROCEDURES.md] + B --> C + B --> D[SECURITY_PROCEDURES.md] + C --> D + + E[Scripts] --> C + F[Helm Charts] --> A + F --> B + G[Monitoring] --> C + G --> D +``` + +## Additional Resources + +### 🔗 External References + +| Resource | Link | Purpose | +|----------|------|---------| +| **Hyperledger Fabric CA Documentation** | [Official Docs](https://hyperledger-fabric-ca.readthedocs.io/) | Official reference | +| **Kubernetes Documentation** | [k8s.io](https://kubernetes.io/docs/) | Platform reference | +| **Helm Documentation** | [helm.sh](https://helm.sh/docs/) | Deployment tools | +| **Security Best Practices** | [NIST Framework](https://www.nist.gov/cyberframework) | Security guidelines | + +### 📞 Support and Contact + +| Type | Contact | Purpose | +|------|---------|---------| +| **Technical Support** | Platform Team | Infrastructure issues | +| **Security Issues** | Security Team | Security incidents, vulnerabilities | +| **Documentation Updates** | Documentation Team | Content improvements | +| **Emergency Escalation** | On-call Manager | Critical incidents | + +## Version History + +| Version | Date | Changes | Author | +|---------|------|---------|--------| +| 1.0 | 2024-09-02 | Initial documentation creation | System | +| | | Complete CA infrastructure documentation | | +| | | Security procedures and compliance | | +| | | Operational procedures and monitoring | | + +## Compliance and Governance + +### 📋 Document Classification +- **README.md**: Internal Use +- **TECHNICAL_SPECS.md**: Internal Use +- **OPERATIONAL_PROCEDURES.md**: Internal Use +- **SECURITY_PROCEDURES.md**: Confidential + +### 🔒 Access Control +- **Read Access**: All development and operations team members +- **Write Access**: Platform leads, documentation maintainers +- **Security Docs**: Security team approval required for changes + +### 📊 Usage Analytics +- Documentation access patterns monitored +- Most frequently accessed sections identified +- User feedback collected for improvements + +This documentation index provides a comprehensive overview of all CA infrastructure documentation, helping users quickly find the information they need for their specific roles and tasks. diff --git a/hyperledger-fabric-network/ca/README.md b/hyperledger-fabric-network/ca/README.md new file mode 100644 index 0000000..9f2b387 --- /dev/null +++ b/hyperledger-fabric-network/ca/README.md @@ -0,0 +1,275 @@ +# Hyperledger Fabric Certificate Authority (CA) Documentation + +This directory contains the complete Certificate Authority infrastructure for the Hyperledger Fabric network, including Root CA, Intermediate CAs, deployment scripts, and management tools. + +## Overview + +The CA infrastructure provides: +- **Root CA**: Central certificate authority for the network +- **Intermediate CAs**: Organization-specific certificate authorities (CBO, Investor, Verifier, Greenstand) +- **Automated enrollment**: Scripts for identity registration and certificate enrollment +- **Kubernetes deployment**: Helm charts for scalable CA deployment +- **Backup/restore**: Complete CA data backup and restoration capabilities + +## Directory Structure + +``` +ca/ +├── helm-charts/ # Helm deployment charts +│ ├── root-ca/ # Root CA deployment +│ ├── cbo-ca/ # CBO organization CA +│ ├── investor-ca/ # Investor organization CA +│ ├── verifier-ca/ # Verifier organization CA +│ ├── greenstand-ca/ # Greenstand organization CA +│ └── fabric-ca-client/ # CA client pod deployment +├── scripts/ # Management and deployment scripts +│ ├── create-ca-secrets.sh # Kubernetes secret creation +│ ├── enroll-admin.sh # Admin enrollment +│ ├── register-identities.sh # Identity registration +│ ├── enroll-ica.sh # Intermediate CA enrollment +│ ├── backup-ca.sh # CA backup script +│ └── restore-ca.sh # CA restoration script +├── fabric-ca/ # CA server configurations +│ ├── root-ca/ +│ ├── cbo-ca/ +│ ├── investor-ca/ +│ ├── verifier-ca/ +│ └── greenstand-ca/ +└── README.md # This documentation +``` + +## Certificate Authority Hierarchy + +``` +Root CA (root-ca) +├── CBO-CA (cbo-ca) # CBO organization certificates +├── Investor-CA (investor-ca) # Investor organization certificates +├── Verifier-CA (verifier-ca) # Verifier organization certificates +└── Greenstand-CA (greenstand-ca) # Greenstand organization certificates +``` + +## Quick Start + +### 1. Deploy Root CA +```bash +cd helm-charts/root-ca +helm install root-ca . -n hlf-ca --create-namespace +``` + +### 2. Deploy CA Client +```bash +cd helm-charts/fabric-ca-client +kubectl apply -f fabric-ca-client.yaml +``` + +### 3. Enroll Admin +```bash +cd scripts +./enroll-admin.sh +``` + +### 4. Register Intermediate CAs +```bash +./register-identities.sh +``` + +### 5. Deploy Intermediate CAs +```bash +cd ../helm-charts/cbo-ca +helm install cbo-ca . -n hlf-ca + +cd ../investor-ca +helm install investor-ca . -n hlf-ca + +cd ../verifier-ca +helm install verifier-ca . -n hlf-ca +``` + +### 6. Enroll Intermediate CAs +```bash +cd ../../scripts +./enroll-ica.sh +``` + +### 7. Create Kubernetes Secrets +```bash +./create-ca-secrets.sh +``` + +## Configuration + +### Root CA Configuration +- **Image**: hyperledger/fabric-ca:1.5.12 +- **Port**: 7054 +- **Storage**: 2Gi persistent volume +- **TLS**: Enabled with custom certificates +- **Database**: SQLite3 (configurable to PostgreSQL/MySQL) + +### Intermediate CA Configuration +- **Parent**: Root CA +- **Organizations**: CBO, Investor, Verifier, Greenstand +- **Auto-enrollment**: Configured for MSP and TLS certificates +- **Storage**: 2Gi per CA instance + +## Management Scripts + +### Identity Management +```bash +# Enroll admin identity +./enroll-admin.sh + +# Register new intermediate CA +./register-identities.sh + +# Enroll intermediate CAs +./enroll-ica.sh +``` + +### Secret Management +```bash +# Create all CA secrets +./create-ca-secrets.sh + +# Backup CA data +./backup-ca.sh + +# Restore CA data +./restore-ca.sh +``` + +## Helm Charts + +### Root CA Chart +- **Location**: `helm-charts/root-ca/` +- **Purpose**: Deploys Root Certificate Authority +- **Features**: TLS-enabled, persistent storage, custom CSR configuration + +### Intermediate CA Charts +- **Locations**: `helm-charts/{org}-ca/` +- **Purpose**: Deploy organization-specific CAs +- **Features**: Parent CA integration, automatic enrollment, TLS configuration + +### CA Client Chart +- **Location**: `helm-charts/fabric-ca-client/` +- **Purpose**: Provides fabric-ca-client for enrollment operations +- **Features**: Persistent client data, configuration management + +## Operations + +### Daily Operations +```bash +# Check CA pod status +kubectl get pods -n hlf-ca + +# View CA logs +kubectl logs -n hlf-ca -l app=root-ca + +# Check certificate expiry +kubectl exec -n hlf-ca fabric-ca-client-0 -- \ + fabric-ca-client certificate list --tls.certfiles /data/hyperledger/fabric-ca-client/root-ca/tls-cert.pem +``` + +### Backup Operations +```bash +# Create backup +./scripts/backup-ca.sh + +# Verify backup contents +tar -tzf fabric-ca-backup-*.tgz | head -20 + +# Store backup securely (off-cluster) +``` + +### Certificate Renewal +```bash +# Check certificate expiry +for ca in root-ca cbo-ca investor-ca verifier-ca; do + echo "Checking $ca certificate expiry..." + kubectl exec -n hlf-ca $ca-0 -- \ + openssl x509 -in /etc/hyperledger/fabric-ca-server/ca-cert.pem -noout -enddate +done + +# Renew certificates (if needed) +# Follow certificate renewal runbook +``` + +## Security Considerations + +### Access Control +- **RBAC**: Kubernetes RBAC limits CA access +- **Network policies**: Restrict CA network access +- **Secrets**: TLS certificates stored as Kubernetes secrets +- **Encryption**: All CA communications use TLS + +### Certificate Management +- **Root CA**: Highest security - air-gapped if possible +- **Intermediate CAs**: Organization-isolated +- **Key protection**: Private keys stored securely in persistent volumes +- **Certificate rotation**: Regular certificate renewal procedures + +## Troubleshooting + +### Common Issues + +#### CA Pod Not Starting +```bash +# Check pod status and events +kubectl describe pod -n hlf-ca root-ca-0 + +# Check persistent volume claims +kubectl get pvc -n hlf-ca + +# Verify TLS certificates +kubectl get secret -n hlf-ca | grep tls +``` + +#### Enrollment Failures +```bash +# Check CA client connectivity +kubectl exec -n hlf-ca fabric-ca-client-0 -- \ + fabric-ca-client getcainfo -u https://root-ca.hlf-ca.svc.cluster.local:7054 + +# Verify TLS certificate +kubectl exec -n hlf-ca fabric-ca-client-0 -- \ + ls -la /data/hyperledger/fabric-ca-client/root-ca/ +``` + +#### Certificate Issues +```bash +# Validate certificate chain +kubectl exec -n hlf-ca fabric-ca-client-0 -- \ + openssl verify -CAfile /data/hyperledger/fabric-ca-client/root-ca/msp/cacerts/root-ca-hlf-ca-svc-cluster-local-7054.pem \ + /data/hyperledger/fabric-ca-client/cbo-ca/msp/signcerts/cert.pem +``` + +## Integration + +### With Peer Networks +- CAs provide certificates for peer MSP and TLS +- Certificate secrets automatically created for peer deployments +- Integration with certificate monitoring system + +### With Certificate Monitoring +- CA certificates monitored for expiry +- Automated alerts for CA certificate issues +- Health metrics exported to Prometheus + +### With CI/CD Pipeline +- CA validation in deployment pipeline +- Automated certificate checks +- Integration with Jenkins/GitHub Actions + +## Maintenance + +### Regular Tasks +- **Weekly**: Check CA pod health and logs +- **Monthly**: Review certificate expiry dates +- **Quarterly**: Perform CA backup +- **Annually**: Plan certificate renewal cycle + +### Emergency Procedures +- **CA failure**: Restore from backup using restore-ca.sh +- **Certificate expiry**: Emergency certificate renewal +- **Security breach**: Revoke compromised certificates + +This CA infrastructure provides a robust foundation for certificate management in your Hyperledger Fabric network with comprehensive automation, monitoring, and operational procedures. diff --git a/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client-config.yaml b/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client-config.yaml new file mode 100644 index 0000000..bf362c4 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client-config.yaml @@ -0,0 +1,176 @@ + +############################################################################# +# This is a configuration file for the fabric-ca-client command. +# +# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES +# ------------------------------------------------ +# Each configuration element can be overridden via command line +# arguments or environment variables. The precedence for determining +# the value of each element is as follows: +# 1) command line argument +# Examples: +# a) --url https://localhost:7054 +# To set the fabric-ca server url +# b) --tls.client.certfile certfile.pem +# To set the client certificate for TLS +# 2) environment variable +# Examples: +# a) FABRIC_CA_CLIENT_URL=https://localhost:7054 +# To set the fabric-ca server url +# b) FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE=certfile.pem +# To set the client certificate for TLS +# 3) configuration file +# 4) default value (if there is one) +# All default values are shown beside each element below. +# +# FILE NAME ELEMENTS +# ------------------ +# The value of all fields whose name ends with "file" or "files" are +# name or names of other files. +# For example, see "tls.certfiles" and "tls.client.certfile". +# The value of each of these fields can be a simple filename, a +# relative path, or an absolute path. If the value is not an +# absolute path, it is interpreted as being relative to the location +# of this configuration file. +# +############################################################################# + +############################################################################# +# Client Configuration +############################################################################# + +# URL of the Fabric-ca-server (default: http://localhost:7054) +url: https://verifier-ca.hlf-ca.svc.cluster.local:7054 + +# Membership Service Provider (MSP) directory +# This is useful when the client is used to enroll a peer or orderer, so +# that the enrollment artifacts are stored in the format expected by MSP. +mspdir: /etc/hyperledger/fabric-ca-client/peer0.verifier/msp + +############################################################################# +# TLS section for secure socket connection +# +# certfiles - PEM-encoded list of trusted root certificate files +# client: +# certfile - PEM-encoded certificate file for when client authentication +# is enabled on server +# keyfile - PEM-encoded key file for when client authentication +# is enabled on server +############################################################################# +tls: + # TLS section for secure socket connection + certfiles: + client: + certfile: + keyfile: + +############################################################################# +# Certificate Signing Request section for generating the CSR for an +# enrollment certificate (ECert) +# +# cn - Used by CAs to determine which domain the certificate is to be generated for +# +# keyrequest - Properties to use when generating a private key. +# algo - key generation algorithm to use +# size - size of key to generate +# reusekey - reuse existing key during reenrollment +# +# serialnumber - The serialnumber field, if specified, becomes part of the issued +# certificate's DN (Distinguished Name). For example, one use case for this is +# a company with its own CA (Certificate Authority) which issues certificates +# to its employees and wants to include the employee's serial number in the DN +# of its issued certificates. +# WARNING: The serialnumber field should not be confused with the certificate's +# serial number which is set by the CA but is not a component of the +# certificate's DN. +# +# names - A list of name objects. Each name object should contain at least one +# "C", "L", "O", or "ST" value (or any combination of these) where these +# are abbreviations for the following: +# "C": country +# "L": locality or municipality (such as city or town name) +# "O": organization +# "OU": organizational unit, such as the department responsible for owning the key; +# it can also be used for a "Doing Business As" (DBS) name +# "ST": the state or province +# +# Note that the "OU" or organizational units of an ECert are always set according +# to the values of the identities type and affiliation. OUs are calculated for an enroll +# as OU=, OU=, ..., OU=. For example, an identity +# of type "client" with an affiliation of "org1.dept2.team3" would have the following +# organizational units: OU=client, OU=org1, OU=dept2, OU=team3 +# +# hosts - A list of host names for which the certificate should be valid +# +############################################################################# +csr: + cn: peer0.verifier + keyrequest: + algo: ecdsa + size: 256 + reusekey: false + serialnumber: + names: + - C: US + ST: North Carolina + L: + O: Hyperledger + OU: Fabric + hosts: + - fabric-ca-client + +############################################################################# +# Registration section used to register a new identity with fabric-ca server +# +# name - Unique name of the identity +# type - Type of identity being registered (e.g. 'peer, app, user') +# affiliation - The identity's affiliation +# maxenrollments - The maximum number of times the secret can be reused to enroll. +# Specially, -1 means unlimited; 0 means to use CA's max enrollment +# value. +# attributes - List of name/value pairs of attribute for identity +############################################################################# +id: + name: + type: + affiliation: + maxenrollments: 0 + attributes: + # - name: + # value: + +############################################################################# +# Enrollment section used to enroll an identity with fabric-ca server +# +# profile - Name of the signing profile to use in issuing the certificate +# label - Label to use in HSM operations +############################################################################# +enrollment: + profile: + label: + +############################################################################# +# Name of the CA to connect to within the fabric-ca server +############################################################################# +caname: + +############################################################################# +# BCCSP (BlockChain Crypto Service Provider) section allows to select which +# crypto implementation library to use +############################################################################# +bccsp: + default: SW + sw: + hash: SHA2 + security: 256 + filekeystore: + # The directory used for the software file-based keystore + keystore: msp/keystore + +############################################################################# +# Idemix curve ID specifies the Elliptic Curve used by Identity Mixer. +# It can be any of: {"amcl.Fp256bn", "gurvy.Bn254", "amcl.Fp256Miraclbn"}. +# If unspecified, it defaults to 'amcl.Fp256bn'. +############################################################################# +idemixCurveID: amcl.Fp256bn + diff --git a/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client.yaml b/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client.yaml new file mode 100644 index 0000000..bac3f40 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/fabric-ca-client/fabric-ca-client.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: fabric-ca-client + namespace: hlf-ca +spec: + serviceName: fabric-ca-client + replicas: 1 + selector: + matchLabels: + app: fabric-ca-client + template: + metadata: + labels: + app: fabric-ca-client + spec: + containers: + - name: fabric-ca-client + image: hyperledger/fabric-ca:1.5.7 + command: ["/bin/bash", "-c", "--"] + args: + - | + while true; do sleep 3600; done + volumeMounts: + - name: ca-client-config + mountPath: /etc/hyperledger/fabric-ca-client + - name: client-data + mountPath: /data + volumes: + - name: ca-client-config + configMap: + name: ca-client-config + volumeClaimTemplates: + - metadata: + name: client-data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + storageClassName: standard + diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/Chart.yaml b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/Chart.yaml new file mode 100644 index 0000000..9d2839b --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: greenstand-ca +description: Hyperledger Fabric intermediate CA for Greenstand +type: application +version: 0.1.0 +appVersion: 1.5.12 \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml new file mode 100644 index 0000000..ed975b1 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml @@ -0,0 +1,46 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp new file mode 100644 index 0000000..59e17aa --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp @@ -0,0 +1,63 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + # Set the Fabric CA server's home directory within the container. + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + # Set the logical name of the CA. This is used as the + # certificate "Common Name" and to tag issued certificates. + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + # Configure the listening port of the CA server. + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + # Configure the URL of the parent CA. When specified, the + # intermediate CA's certificate will be signed by the parent CA + # instead of being self‑signed. The parent URL must embed + # credentials registered at the parent CA (hf.IntermediateCA=true) + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + # Enable TLS for the CA server. Without TLS, the server will + # listen on HTTP and be vulnerable to network attacks【414858305040423†L546-L551】. + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + # Provide a list of hostnames for the CSR. The Fabric CA will + # embed these values in the certificate's SAN extension so that + # clients can verify the certificate when connecting via any of + # these names【414858305040423†L330-L333】. + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + volumeMounts: + # Persist the CA's state (keys, certificates, configuration) in + # a persistent volume. Without a volume, data will be lost if the + # pod is rescheduled. + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp-startingPoint b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp-startingPoint new file mode 100644 index 0000000..ed975b1 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp-startingPoint @@ -0,0 +1,46 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp1 b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp1 new file mode 100644 index 0000000..ff5f0b3 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkp1 @@ -0,0 +1,64 @@ +{{- if .Values.intermediateCA.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + - name: FABRIC_CA_SERVER_TLS_CERTFILE + value: /etc/hyperledger/fabric-ca-server-config/cert.pem + - name: FABRIC_CA_SERVER_TLS_KEYFILE + value: /etc/hyperledger/fabric-ca-server-config/key.pem + - name: FABRIC_CA_SERVER_TLS_CHAINFILE + value: /etc/hyperledger/fabric-ca-server-config/ca-chain.pem + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + - name: tls-cert + mountPath: /etc/hyperledger/fabric-ca-server-config + readOnly: true + - name: ca-msp + mountPath: /etc/hyperledger/fabric-ca-server/msp + readOnly: false + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} + - name: tls-cert + secret: + secretName: {{ .Values.intermediateCA.tls.secretName }} + - name: ca-msp + secret: + secretName: {{ .Values.intermediateCA.msp.secretName }} +{{- end }} diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkpios b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkpios new file mode 100644 index 0000000..e8978ad --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/deployment.yaml.bkpios @@ -0,0 +1,57 @@ +{{- if .Values.intermediateCA.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_CN + value: {{ .Values.intermediateCA.csr.cn }} + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + - name: FABRIC_CA_SERVER_INTERMEDIATE_TLS_CERTFILES + value: "/etc/hyperledger/fabric-ca-server/root-tls-cert.pem" + - name: FABRIC_CA_SERVER_INTERMEDIATE_PARENTSERVER_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + - name: root-tls-cert + mountPath: /etc/hyperledger/fabric-ca-server/root-tls-cert.pem + subPath: root-tls-cert.pem + readOnly: true + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: {{ .Values.intermediateCA.storage.pvcName }} + - name: root-tls-cert + secret: + secretName: {{ .Values.intermediateCA.tls.secretName }} +{{- end }} diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml new file mode 100644 index 0000000..2d3c8f6 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.intermediateCA.storage.pvcName }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + accessModes: + - {{ .Values.intermediateCA.storage.accessMode | quote }} + resources: + requests: + storage: {{ .Values.intermediateCA.storage.size | quote }} + storageClassName: {{ .Values.intermediateCA.storage.storageClass | quote }} +{{- end }} diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml.bkp-startingPoint b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml.bkp-startingPoint new file mode 100644 index 0000000..0e654d6 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/pvc.yaml.bkp-startingPoint @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-{{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + accessModes: + - {{ .Values.intermediateCA.storage.accessMode }} + resources: + requests: + storage: {{ .Values.intermediateCA.storage.size }} + storageClassName: {{ .Values.intermediateCA.storage.storageClass }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/service.yaml b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/service.yaml new file mode 100644 index 0000000..da5f903 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/templates/service.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + selector: + app: {{ .Values.intermediateCA.name }} + ports: + - name: ca-port + port: {{ .Values.intermediateCA.port }} + targetPort: ca-port +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/values.yaml b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/values.yaml new file mode 100644 index 0000000..1698aa9 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/greenstand-ca/values.yaml @@ -0,0 +1,41 @@ +intermediateCA: + enabled: true + name: greenstand-ca + namespace: hlf-ca + + image: + repository: hyperledger/fabric-ca + tag: 1.5.12 + pullPolicy: IfNotPresent + + port: 7054 + + storage: + accessMode: ReadWriteOnce + size: 2Gi + storageClass: do-block-storage + pvcName: greenstand-ca-pvc + + parentID: greenstand-ca + parentSecret: greenstandcapw + parentHost: root-ca.hlf-ca.svc.cluster.local + + csr: + cn: greenstand-ca + hosts: + - greenstand-ca + - greenstand-ca.hlf-ca.svc.cluster.local + - localhost + + tls: + enabled: true + secretName: root-tls-cert # This must match the secret with the root ca-cert.pem + + msp: + secretName: greenstand-ca-msp + + bootstrapUser: greenstand-ca + bootstrapPassword: greenstandcapw + + service: + port: 7054 diff --git a/hyperledger-fabric-network/ca/helm-charts/investor-ca/Chart.yaml b/hyperledger-fabric-network/ca/helm-charts/investor-ca/Chart.yaml new file mode 100644 index 0000000..7c51fd4 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/investor-ca/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: investor-ca +description: Hyperledger Fabric intermediate CA for Investor +type: application +version: 0.1.0 +appVersion: 1.5.12 \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/deployment.yaml b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/deployment.yaml new file mode 100644 index 0000000..90ee72f --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/deployment.yaml @@ -0,0 +1,46 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/pvc.yaml b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/pvc.yaml new file mode 100644 index 0000000..0e654d6 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-{{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + accessModes: + - {{ .Values.intermediateCA.storage.accessMode }} + resources: + requests: + storage: {{ .Values.intermediateCA.storage.size }} + storageClassName: {{ .Values.intermediateCA.storage.storageClass }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/service.yaml b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/service.yaml new file mode 100644 index 0000000..da5f903 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/investor-ca/templates/service.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + selector: + app: {{ .Values.intermediateCA.name }} + ports: + - name: ca-port + port: {{ .Values.intermediateCA.port }} + targetPort: ca-port +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/investor-ca/values.yaml b/hyperledger-fabric-network/ca/helm-charts/investor-ca/values.yaml new file mode 100644 index 0000000..e646784 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/investor-ca/values.yaml @@ -0,0 +1,43 @@ +# Default values for the Investor intermediate CA chart. + +intermediateCA: + enabled: true + name: investor-ca + namespace: hlf-ca + + image: + repository: hyperledger/fabric-ca + tag: 1.5.12 + pullPolicy: IfNotPresent + + port: 7054 + + storage: + accessMode: ReadWriteOnce + size: 2Gi + storageClass: do-block-storage + pvcName: pvc-investor-ca # Added from second block + + parentID: investor-ca + parentSecret: investorcapw + parentHost: root-ca.hlf-ca.svc.cluster.local + + csr: + cn: investor-ca # Added from second block + hosts: + - investor-ca + - investor-ca.hlf-ca.svc.cluster.local + - localhost + + tls: + enabled: true + secretName: investor-ca-tls-cert + + msp: + secretName: investor-ca-msp + + bootstrapUser: investor-ca + bootstrapPassword: investorcapw + + service: + port: 7054 \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/root-ca/Chart.yaml b/hyperledger-fabric-network/ca/helm-charts/root-ca/Chart.yaml new file mode 100644 index 0000000..a95e77d --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/root-ca/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: fabric-ca +description: Fabric CA deployment chart for Hyperledger Fabric Root and Intermediate CAs +type: application +version: 0.1.0 +appVersion: "1.5.12" diff --git a/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/deployment.yaml b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/deployment.yaml new file mode 100644 index 0000000..bbb46c1 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.rootCA.name }} + namespace: {{ .Values.rootCA.namespace }} + labels: + app: {{ .Values.rootCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.rootCA.name }} + template: + metadata: + labels: + app: {{ .Values.rootCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.rootCA.image.repository }}:{{ .Values.rootCA.image.tag }}" + imagePullPolicy: {{ .Values.rootCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.rootCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.rootCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.rootCA.port }}" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "root-ca,root-ca.hlf-ca.svc.cluster.local,localhost" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.rootCA.name }} diff --git a/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/pvc.yaml b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/pvc.yaml new file mode 100644 index 0000000..3ee8fcf --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-{{ .Values.rootCA.name }} + namespace: {{ .Values.rootCA.namespace }} + labels: + app: {{ .Values.rootCA.name }} +spec: + accessModes: + - {{ .Values.rootCA.storage.accessMode }} + resources: + requests: + storage: {{ .Values.rootCA.storage.size }} + storageClassName: {{ .Values.rootCA.storage.storageClass }} diff --git a/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/service.yaml b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/service.yaml new file mode 100644 index 0000000..7f4343a --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/root-ca/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.rootCA.name }} + namespace: {{ .Values.rootCA.namespace }} + labels: + app: {{ .Values.rootCA.name }} +spec: + selector: + app: {{ .Values.rootCA.name }} + ports: + - protocol: TCP + port: {{ .Values.rootCA.port }} + targetPort: ca-port + type: ClusterIP diff --git a/hyperledger-fabric-network/ca/helm-charts/root-ca/values.yaml b/hyperledger-fabric-network/ca/helm-charts/root-ca/values.yaml new file mode 100644 index 0000000..59cc9ae --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/root-ca/values.yaml @@ -0,0 +1,28 @@ +rootCA: + enabled: true + name: root-ca + namespace: hlf-ca + + image: + repository: hyperledger/fabric-ca + tag: 1.5.12 + pullPolicy: IfNotPresent + + port: 7054 + + tlsSecret: root-ca-tls-cert + + configMountPath: /etc/hyperledger/fabric-ca-server-config + + storage: + accessMode: ReadWriteOnce + size: 2Gi + storageClass: do-block-storage + + # ? Add this section + csr: + cn: root-ca + hosts: + - root-ca + - root-ca.hlf-ca.svc.cluster.local + - localhost diff --git a/hyperledger-fabric-network/ca/helm-charts/verifier-ca/Chart.yaml b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/Chart.yaml new file mode 100644 index 0000000..94598b9 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: verifier-ca +description: Hyperledger Fabric intermediate CA for Verifier +type: application +version: 0.1.0 +appVersion: 1.5.12 \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/deployment.yaml b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/deployment.yaml new file mode 100644 index 0000000..90ee72f --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/deployment.yaml @@ -0,0 +1,46 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.intermediateCA.name }} + template: + metadata: + labels: + app: {{ .Values.intermediateCA.name }} + spec: + containers: + - name: fabric-ca + image: "{{ .Values.intermediateCA.image.repository }}:{{ .Values.intermediateCA.image.tag }}" + imagePullPolicy: {{ .Values.intermediateCA.image.pullPolicy }} + ports: + - containerPort: {{ .Values.intermediateCA.port }} + name: ca-port + env: + - name: FABRIC_CA_HOME + value: /etc/hyperledger/fabric-ca-server + - name: FABRIC_CA_SERVER_CA_NAME + value: {{ .Values.intermediateCA.name }} + - name: FABRIC_CA_SERVER_PORT + value: "{{ .Values.intermediateCA.port }}" + - name: FABRIC_CA_SERVER_PARENT_URL + value: "https://{{ .Values.intermediateCA.parentID }}:{{ .Values.intermediateCA.parentSecret }}@{{ .Values.intermediateCA.parentHost }}:7054" + - name: FABRIC_CA_SERVER_TLS_ENABLED + value: "true" + - name: FABRIC_CA_SERVER_CSR_HOSTS + value: "{{ join "," .Values.intermediateCA.csr.hosts }}" + volumeMounts: + - name: fabric-ca-data + mountPath: /etc/hyperledger/fabric-ca-server + volumes: + - name: fabric-ca-data + persistentVolumeClaim: + claimName: pvc-{{ .Values.intermediateCA.name }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/pvc.yaml b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/pvc.yaml new file mode 100644 index 0000000..0e654d6 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-{{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + accessModes: + - {{ .Values.intermediateCA.storage.accessMode }} + resources: + requests: + storage: {{ .Values.intermediateCA.storage.size }} + storageClassName: {{ .Values.intermediateCA.storage.storageClass }} +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/service.yaml b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/service.yaml new file mode 100644 index 0000000..da5f903 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/templates/service.yaml @@ -0,0 +1,16 @@ +{{- if .Values.intermediateCA.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.intermediateCA.name }} + namespace: {{ .Values.intermediateCA.namespace }} + labels: + app: {{ .Values.intermediateCA.name }} +spec: + selector: + app: {{ .Values.intermediateCA.name }} + ports: + - name: ca-port + port: {{ .Values.intermediateCA.port }} + targetPort: ca-port +{{- end -}} \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/helm-charts/verifier-ca/values.yaml b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/values.yaml new file mode 100644 index 0000000..a19a876 --- /dev/null +++ b/hyperledger-fabric-network/ca/helm-charts/verifier-ca/values.yaml @@ -0,0 +1,41 @@ +intermediateCA: + enabled: true + name: verifier-ca + namespace: hlf-ca + + image: + repository: hyperledger/fabric-ca + tag: 1.5.12 + pullPolicy: IfNotPresent + + port: 7054 + + storage: + accessMode: ReadWriteOnce + size: 2Gi + storageClass: do-block-storage + pvcName: pvc-verifier-ca # Added from second block + + parentID: verifier-ca + parentSecret: verifiercapw + parentHost: root-ca.hlf-ca.svc.cluster.local + + csr: + cn: verifier-ca # Added from second block + hosts: + - verifier-ca + - verifier-ca.hlf-ca.svc.cluster.local + - localhost + + tls: + enabled: true + secretName: verifier-ca-tls-cert + + msp: + secretName: verifier-ca-msp + + bootstrapUser: verifier-ca + bootstrapPassword: verifiercapw + + service: + port: 7054 \ No newline at end of file diff --git a/hyperledger-fabric-network/ca/scripts/backup-ca.sh b/hyperledger-fabric-network/ca/scripts/backup-ca.sh new file mode 100644 index 0000000..72c8a99 --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/backup-ca.sh @@ -0,0 +1,162 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ------------------------------------------------------------------------------ +# Hyperledger Fabric CA backup script +# - Backs up CA server data dirs from pods (DB, certs, CSR, keys) +# - Backs up fabric-ca-client enrollments from client pod +# - Backs up K8s secrets & configmaps in the CA namespace +# - Backs up Helm release configs in the CA namespace +# +# Usage: +# ./backup-ca.sh [--namespace hlf-ca] [--client-pod fabric-ca-client-0] \ +# [--label "app.kubernetes.io/component=fabric-ca"] +# +# Result: +# ./fabric-ca-backup-YYYY-MM-DD_HHMMSS.tgz +# +# Notes: +# - Requires: kubectl, jq, helm (for Helm release manifests) +# - The script is read-only on the cluster; it just fetches and packages. +# ------------------------------------------------------------------------------ + +NS="${NS:-hlf-ca}" +CLIENT_POD="${CLIENT_POD:-fabric-ca-client-0}" +CA_LABEL="${CA_LABEL:-app in (root-ca,greenstand-ca,cbo-ca,investor-ca,verifier-ca)}" +OUTDIR="${OUTDIR:-./backup-ca}" +STAMP="$(date +%F_%H%M%S)" +ARCHIVE="fabric-ca-backup-${STAMP}.tgz" + +# Parse args (tiny parser) +while [[ $# -gt 0 ]]; do + case "$1" in + --namespace|-n) NS="$2"; shift 2;; + --client-pod) CLIENT_POD="$2"; shift 2;; + --label) CA_LABEL="$2"; shift 2;; + --outdir) OUTDIR="$2"; shift 2;; + -h|--help) + grep -E '^# ' "$0" | sed 's/^# //' + exit 0;; + *) + echo "Unknown arg: $1" >&2; exit 1;; + esac +done + +echo "Namespace : $NS" +echo "CA selector label : $CA_LABEL" +echo "CA client pod : $CLIENT_POD" +echo "Output dir : $OUTDIR" +echo + +mkdir -p "$OUTDIR" + +# ------------------------------------------------------------------------------ +# 1) Discover CA server pods (Root + Intermediate CAs) +# ------------------------------------------------------------------------------ +echo ">> Discovering CA pods in $NS ..." +mapfile -t CA_PODS < <(kubectl -n "$NS" get pods -l "$CA_LABEL" -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}') +if [[ "${#CA_PODS[@]}" -eq 0 ]]; then + echo "No CA pods found with label: $CA_LABEL in namespace: $NS" >&2 + exit 1 +fi +printf " Found CA pods:\n"; printf " - %s\n" "${CA_PODS[@]}"; echo + +# ------------------------------------------------------------------------------ +# 2) Backup CA server data from each CA pod +# Common locations (adjust if your container image differs): +# - /etc/hyperledger/fabric-ca-server (config, certs, db) +# - /data/hyperledger/fabric-ca-server (PVC mount in many charts) +# ------------------------------------------------------------------------------ +for pod in "${CA_PODS[@]}"; do + echo ">> Backing up server data from pod: $pod" + + # Use tar-from-pod to preserve perms & symlinks + TMP_DIR="$(mktemp -d)" + ( + set -x + # Try both common paths; ignore if missing + kubectl -n "$NS" exec "$pod" -- sh -lc 'tar -C / -czf - \ + etc/hyperledger/fabric-ca-server 2>/dev/null || true' > "${TMP_DIR}/server-etc.tgz" + kubectl -n "$NS" exec "$pod" -- sh -lc 'tar -C / -czf - \ + data/hyperledger/fabric-ca-server 2>/dev/null || true' > "${TMP_DIR}/server-data.tgz" + ) + + DEST_DIR="${OUTDIR}/${pod}" + mkdir -p "$DEST_DIR" + # Store tarballs raw (so we can untar to exact paths on restore) + mv "${TMP_DIR}/server-etc.tgz" "${DEST_DIR}/server-etc.tgz" + mv "${TMP_DIR}/server-data.tgz" "${DEST_DIR}/server-data.tgz" + rm -rf "$TMP_DIR" + + echo " Saved: ${DEST_DIR}/server-etc.tgz, server-data.tgz" +done +echo + +# ------------------------------------------------------------------------------ +# 3) Backup the fabric-ca-client enrollments +# Typical path: /data/hyperledger/fabric-ca-client +# (Your earlier logs confirm this path.) +# ------------------------------------------------------------------------------ +echo ">> Backing up fabric-ca-client enrollments from pod: $CLIENT_POD" +if kubectl -n "$NS" get pod "$CLIENT_POD" >/dev/null 2>&1; then + kubectl -n "$NS" exec "$CLIENT_POD" -- sh -lc 'tar -C / -czf - data/hyperledger/fabric-ca-client' \ + > "${OUTDIR}/fabric-ca-client.tgz" + echo " Saved: ${OUTDIR}/fabric-ca-client.tgz" +else + echo " WARN: client pod $CLIENT_POD not found; skipping client enrollments" +fi +echo + +# ------------------------------------------------------------------------------ +# 4) Backup Kubernetes secrets & configmaps in CA namespace +# (This captures TLS certs/keys, CA configs, issuers, etc.) +# ------------------------------------------------------------------------------ +echo ">> Exporting all secrets & configmaps in namespace: $NS" +kubectl -n "$NS" get secret -o yaml > "${OUTDIR}/k8s-secrets-${NS}.yaml" +kubectl -n "$NS" get cm -o yaml > "${OUTDIR}/k8s-configmaps-${NS}.yaml" +echo " Saved: k8s-secrets-${NS}.yaml, k8s-configmaps-${NS}.yaml" +echo + +# ------------------------------------------------------------------------------ +# 5) Backup Helm release configs for the namespace (if helm is in use here) +# ------------------------------------------------------------------------------ +if command -v helm >/dev/null 2>&1; then + echo ">> Capturing Helm releases in $NS" + mapfile -t HELM_RELEASES < <(helm list -n "$NS" -o json | jq -r '.[].name') + if [[ "${#HELM_RELEASES[@]}" -gt 0 ]]; then + for rel in "${HELM_RELEASES[@]}"; do + mkdir -p "${OUTDIR}/helm-releases/${rel}" + # Get history & manifest + helm history "$rel" -n "$NS" -o yaml > "${OUTDIR}/helm-releases/${rel}/history.yaml" || true + helm get all "$rel" -n "$NS" > "${OUTDIR}/helm-releases/${rel}/all.txt" || true + # If you store Helm release objects as secrets, grab them too: + kubectl -n "$NS" get secret -l "owner=helm,name=${rel}" -o yaml \ + > "${OUTDIR}/helm-releases/${rel}/release-secrets.yaml" || true + done + echo " Saved Helm release details under ${OUTDIR}/helm-releases/" + else + echo " No Helm releases found in ${NS}." + fi +else + echo ">> helm not found in PATH; skipping Helm release capture." +fi +echo + +# ------------------------------------------------------------------------------ +# 6) Sanity: list what we collected +# ------------------------------------------------------------------------------ +echo ">> Collected artifacts:" +( cd "$OUTDIR" && find . -maxdepth 3 -type f | sed 's@^\./@@' | sort ) + +# ------------------------------------------------------------------------------ +# 7) Package +# ------------------------------------------------------------------------------ +echo +echo ">> Creating archive: ${ARCHIVE}" +tar -C "$(dirname "$OUTDIR")" -czf "$ARCHIVE" "$(basename "$OUTDIR")" + +echo +echo "✅ CA backup complete:" +echo " $(pwd)/${ARCHIVE}" +echo " (Keep this archive outside Git; rotate & encrypt as needed.)" + diff --git a/hyperledger-fabric-network/ca/scripts/create-ca-secrets.sh b/hyperledger-fabric-network/ca/scripts/create-ca-secrets.sh new file mode 100644 index 0000000..8990c17 --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/create-ca-secrets.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Create Kubernetes secrets for ICA MSP and TLS +set -e + +NAMESPACE="hlf-ca" +ICAS=("greenstand-ca" "cbo-ca" "investor-ca" "verifier-ca") +BASE_PATH="/root/hyperledger-fabric-network" + +echo "🔐 Creating Kubernetes secrets for each Intermediate CA..." + +for ICA in "${ICAS[@]}"; do + ICA_DIR="${BASE_PATH}/${ICA}" + + MSP_DIR="${ICA_DIR}/msp" + TLS_DIR="${ICA_DIR}/tls" + + echo "📦 Creating secrets for $ICA..." + + TLS_CA=$(find ${TLS_DIR}/tlscacerts -name "*.pem" 2>/dev/null) + TLS_CERT="${TLS_DIR}/signcerts/cert.pem" + TLS_KEY=$(find ${TLS_DIR}/keystore -name "*.pem" | head -n 1) + + if [[ -f "$TLS_CA" && -f "$TLS_CERT" && -f "$TLS_KEY" ]]; then + kubectl create secret generic ${ICA}-tls-cert \ + --from-file=ca.crt=$TLS_CA \ + --from-file=server.crt=$TLS_CERT \ + --from-file=server.key=$TLS_KEY \ + -n ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f - + echo "✅ TLS secret created for $ICA" + else + echo "⚠️ Skipping TLS secret for $ICA — missing files" + fi + + # MSP Secret + if [[ -d "$MSP_DIR" ]]; then + kubectl create secret generic ${ICA}-msp-cert \ + --from-file=signcerts=${MSP_DIR}/signcerts \ + --from-file=keystore=${MSP_DIR}/keystore \ + --from-file=cacerts=${MSP_DIR}/cacerts \ + --from-file=config.yaml=${MSP_DIR}/config.yaml \ + -n ${NAMESPACE} --dry-run=client -o yaml | kubectl apply -f - + echo "✅ MSP secret created for $ICA" + else + echo "⚠️ Skipping MSP secret for $ICA — missing directory" + fi +done + +echo "🎉 All ICA secrets created and applied." + diff --git a/hyperledger-fabric-network/ca/scripts/enroll-admin.sh b/hyperledger-fabric-network/ca/scripts/enroll-admin.sh new file mode 100644 index 0000000..cbaa895 --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/enroll-admin.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Root CA Enroll Admin Script + +set -e + +# Configuration +CA_NAME="root-ca" +NAMESPACE="hlf-ca" +FABRIC_CA_CLIENT_HOME=/data/hyperledger/fabric-ca-client/root-ca +TLS_CERT_PATH=$FABRIC_CA_CLIENT_HOME/tls-cert.pem +CA_HOST="root-ca.hlf-ca.svc.cluster.local:7054" +ADMIN_USER="admin" +ADMIN_PASS="adminpw" + +echo "📂 Setting FABRIC_CA_CLIENT_HOME=$FABRIC_CA_CLIENT_HOME" +export FABRIC_CA_CLIENT_HOME=$FABRIC_CA_CLIENT_HOME + +echo "📥 Creating directories..." +mkdir -p $FABRIC_CA_CLIENT_HOME + +echo "🔍 Fetching Root CA pod name..." +ROOT_CA_POD=$(kubectl get pods -n $NAMESPACE -l app=$CA_NAME -o jsonpath="{.items[0].metadata.name}") +echo "📦 Found pod: $ROOT_CA_POD" + +echo "📦 Copying TLS cert from pod to local..." +kubectl cp $NAMESPACE/$ROOT_CA_POD:/etc/hyperledger/fabric-ca-server/ca-cert.pem ./tls-cert.pem + +echo "📦 Copying TLS cert to fabric-ca-client pod..." +kubectl cp ./tls-cert.pem $NAMESPACE/fabric-ca-client-0:$TLS_CERT_PATH + +echo "🔐 Enrolling admin..." +kubectl exec -n $NAMESPACE fabric-ca-client-0 -- \ + fabric-ca-client enroll \ + --url https://$ADMIN_USER:$ADMIN_PASS@$CA_HOST \ + --tls.certfiles $TLS_CERT_PATH + +echo "✅ Root CA Admin enrolled successfully." + diff --git a/hyperledger-fabric-network/ca/scripts/enroll-ica.sh b/hyperledger-fabric-network/ca/scripts/enroll-ica.sh new file mode 100644 index 0000000..cb4109c --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/enroll-ica.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Enroll Intermediate CA identities (MSP + TLS) +set -e + +NAMESPACE="hlf-ca" +ROOT_CA_URL="https://root-ca.hlf-ca.svc.cluster.local:7054" +TLS_CERT_PATH="/data/hyperledger/fabric-ca-client/root-ca/tls-cert.pem" + +# ICA identities and passwords +declare -A ICAS=( + ["greenstand-ca"]="greenstandcapw" + ["cbo-ca"]="cbocapw" + ["investor-ca"]="investorcapw" + ["verifier-ca"]="verifiercapw" +) + +echo "🔐 Enrolling Intermediate CAs (MSP + TLS)..." + +for ICA in "${!ICAS[@]}"; do + PASSWORD="${ICAS[$ICA]}" + ICA_DIR="/root/hyperledger-fabric-network/${ICA}" + + echo "➡️ Enrolling MSP for $ICA..." + kubectl exec -n $NAMESPACE fabric-ca-client-0 -- \ + fabric-ca-client enroll \ + --url https://$ICA:$PASSWORD@root-ca.hlf-ca.svc.cluster.local:7054 \ + --tls.certfiles $TLS_CERT_PATH \ + --mspdir $ICA_DIR/msp + + echo "➡️ Enrolling TLS for $ICA..." + kubectl exec -n $NAMESPACE fabric-ca-client-0 -- \ + fabric-ca-client enroll \ + --url https://$ICA:$PASSWORD@root-ca.hlf-ca.svc.cluster.local:7054 \ + --tls.certfiles $TLS_CERT_PATH \ + --enrollment.profile tls \ + --mspdir $ICA_DIR/tls + + echo "✅ Enrolled $ICA (MSP + TLS)" +done + +echo "🎉 All Intermediate CAs enrolled successfully." + diff --git a/hyperledger-fabric-network/ca/scripts/notes-guide.sh b/hyperledger-fabric-network/ca/scripts/notes-guide.sh new file mode 100644 index 0000000..76b1394 --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/notes-guide.sh @@ -0,0 +1,25 @@ +cd hyperledger-fabric-network/ca/scripts +chmod +x backup-ca.sh + +./backup-ca.sh \ + --namespace hlf-ca \ + --client-pod fabric-ca-client-0 \ + --label 'app in (root-ca,greenstand-ca,cbo-ca,investor-ca,verifier-ca)' + + +cd hyperledger-fabric-network/ca/scripts +chmod +x restore-ca.sh + +# Basic restore back into hlf-ca +./restore-ca.sh --archive /path/to/fabric-ca-backup-2025-08-08_201755.tgz + +# Only re-apply K8s objects (Secrets/ConfigMaps) +./restore-ca.sh --archive ./fabric-ca-backup-*.tgz --no-data + +# Restore into a different namespace (e.g., a test restore) +kubectl create ns test-ca +./restore-ca.sh --archive ./fabric-ca-backup-*.tgz --namespace test-ca + +# Preview what would happen +./restore-ca.sh --archive ./fabric-ca-backup-*.tgz --dry-run --verbose + diff --git a/hyperledger-fabric-network/ca/scripts/register-identities.sh b/hyperledger-fabric-network/ca/scripts/register-identities.sh new file mode 100644 index 0000000..cbf190d --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/register-identities.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Register Intermediate CA identities with Root CA +set -e + +# Root CA configuration +CA_NAME="root-ca" +NAMESPACE="hlf-ca" +FABRIC_CA_CLIENT_HOME=/data/hyperledger/fabric-ca-client/root-ca +TLS_CERT_PATH=$FABRIC_CA_CLIENT_HOME/tls-cert.pem +CA_HOST="root-ca.hlf-ca.svc.cluster.local:7054" + +# Export environment +export FABRIC_CA_CLIENT_HOME=$FABRIC_CA_CLIENT_HOME + +# ICA identities to register +declare -A ICAS=( + ["greenstand-ca"]="greenstandcapw" + ["cbo-ca"]="cbocapw" + ["investor-ca"]="investorcapw" + ["verifier-ca"]="verifiercapw" +) + +echo "🔐 Registering Intermediate CAs with Root CA..." + +for ICA in "${!ICAS[@]}"; do + PASSWORD="${ICAS[$ICA]}" + + echo "➡️ Registering $ICA with password '$PASSWORD'..." + kubectl exec -n $NAMESPACE fabric-ca-client-0 -- \ + fabric-ca-client register \ + --id.name "$ICA" \ + --id.secret "$PASSWORD" \ + --id.type client \ + --id.attrs "hf.IntermediateCA=true" \ + --tls.certfiles "$TLS_CERT_PATH" \ + --url "https://$CA_HOST" + + echo "✅ Registered $ICA" +done + +echo "🎉 All Intermediate CAs registered successfully." + diff --git a/hyperledger-fabric-network/ca/scripts/restore-ca.sh b/hyperledger-fabric-network/ca/scripts/restore-ca.sh new file mode 100644 index 0000000..69e2bd2 --- /dev/null +++ b/hyperledger-fabric-network/ca/scripts/restore-ca.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# === Defaults === +NS="hlf-ca" +ARCHIVE="" +LABEL_SELECTOR="app in (root-ca,greenstand-ca,cbo-ca,investor-ca,verifier-ca)" +APPLY_K8S="true" +RESTORE_DATA="true" +DRY_RUN="false" +VERBOSE="false" + +usage() { + cat <<'EOF' +Usage: + restore-ca.sh --archive + [--namespace ] + [--label ""] + [--no-k8s] [--no-data] + [--dry-run] [--verbose] + +What it does: + 1) Extracts the backup archive to a temp dir + 2) (default) Applies Secrets/ConfigMaps from the backup into the target namespace (namespaced swap if needed) + 3) (default) Restores CA server data (server-etc.tgz + server-data.tgz) into each CA pod discovered by label: + - copies tarballs into the pod + - extracts to /etc/hyperledger/fabric-ca-server and /data/hyperledger/fabric-ca-server + - then deletes the pod to let Deployment recreate it with the restored data + +Options: + --archive Path to backup archive (required) + --namespace Target namespace (default: hlf-ca) + --label "" Label selector for CA pods (default covers: root/greenstand/cbo/investor/verifier) + --no-k8s Skip restoring K8s Secrets/ConfigMaps + --no-data Skip restoring CA server data into pods + --dry-run Show what would happen, do not modify cluster + --verbose Extra logs + +Examples: + ./restore-ca.sh --archive fabric-ca-backup-2025-08-08_201755.tgz + ./restore-ca.sh --archive ./backup.tgz --namespace test-ca --label 'app in (root-ca)' + ./restore-ca.sh --archive ./backup.tgz --no-data # only re-apply secrets/configmaps +EOF +} + +log() { echo "[$(date +%H:%M:%S)] $*"; } +vlog() { [[ "$VERBOSE" == "true" ]] && echo "[$(date +%H:%M:%S)] $*" || true; } + +# === Parse args === +while [[ $# -gt 0 ]]; do + case "$1" in + --archive) ARCHIVE="$2"; shift 2;; + --namespace) NS="$2"; shift 2;; + --label) LABEL_SELECTOR="$2"; shift 2;; + --no-k8s) APPLY_K8S="false"; shift;; + --no-data) RESTORE_DATA="false"; shift;; + --dry-run) DRY_RUN="true"; shift;; + --verbose) VERBOSE="true"; shift;; + -h|--help) usage; exit 0;; + *) echo "Unknown arg: $1"; usage; exit 1;; + esac +done + +[[ -z "$ARCHIVE" ]] && { echo "ERROR: --archive is required"; usage; exit 1; } +[[ -f "$ARCHIVE" ]] || { echo "ERROR: archive not found: $ARCHIVE"; exit 1; } + +# === Prep temp workspace === +WORKDIR="$(mktemp -d -t ca-restore-XXXXXX)" +cleanup() { rm -rf "$WORKDIR"; } +trap cleanup EXIT + +log "Extracting archive: $ARCHIVE" +tar -xzf "$ARCHIVE" -C "$WORKDIR" + +# Sanity: show what we’ve got +vlog "Archive layout:" +vlog "$(find "$WORKDIR" -maxdepth 2 -type f | sed "s|$WORKDIR/||")" + +# === 1) Restore K8s objects (Secrets/ConfigMaps) === +if [[ "$APPLY_K8S" == "true" ]]; then + for f in k8s-secrets-*.yaml k8s-configmaps-*.yaml; do + SRC="$WORKDIR/$f" + [[ -f "$SRC" ]] || { vlog "Skip missing $f"; continue; } + # Swap namespace in the manifests if needed + TMP="$WORKDIR/$f.patched" + # Replace only explicit "namespace: " occurrences. If no namespace lines present, we’ll apply with -n. + sed "s/^\(\s*namespace:\s*\).*/\1$NS/" "$SRC" > "$TMP" || cp "$SRC" "$TMP" + + if [[ "$DRY_RUN" == "true" ]]; then + log "[DRY-RUN] kubectl apply -n $NS -f $TMP" + else + log "Applying $(basename "$TMP") to namespace $NS" + kubectl apply -n "$NS" -f "$TMP" + fi + done +else + log "Skipping K8s Secrets/ConfigMaps restore (--no-k8s)" +fi + +# === 2) Discover CA pods in target namespace === +if [[ "$RESTORE_DATA" == "true" ]]; then + log "Discovering CA pods in namespace: $NS (selector: $LABEL_SELECTOR)" + mapfile -t CA_PODS < <(kubectl get pods -n "$NS" -l "$LABEL_SELECTOR" -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}') + if [[ ${#CA_PODS[@]} -eq 0 ]]; then + echo "ERROR: No CA pods matched selector in namespace $NS"; exit 1 + fi + printf " Found CA pods:\n"; for p in "${CA_PODS[@]}"; do printf " - %s\n" "$p"; done + + # Build a mapping of -> by using the app label (e.g. root-ca) and matching a dir like root-ca-* + for POD in "${CA_PODS[@]}"; do + APP=$(kubectl -n "$NS" get pod "$POD" -o jsonpath='{.metadata.labels.app}') + if [[ -z "$APP" ]]; then + echo "WARN: Pod $POD has no 'app' label; trying to infer from pod name" + APP="${POD%-*}" # strip trailing hash if any + fi + + # Find dir in archive that starts with APP- + MATCH_DIR="$(find "$WORKDIR" -maxdepth 1 -type d -name "${APP}-*" | head -n1 || true)" + if [[ -z "$MATCH_DIR" ]]; then + echo "WARN: No archive dir matching '${APP}-*' for pod $POD; skipping data restore for this pod" + continue + fi + + ETC_TGZ="$MATCH_DIR/server-etc.tgz" + DATA_TGZ="$MATCH_DIR/server-data.tgz" + if [[ ! -f "$ETC_TGZ" && ! -f "$DATA_TGZ" ]]; then + echo "WARN: No server-*.tgz for $APP in archive; skipping $POD" + continue + fi + + log "Restoring CA data into pod: $POD (from: $(basename "$MATCH_DIR"))" + + if [[ "$DRY_RUN" == "true" ]]; then + [[ -f "$ETC_TGZ" ]] && log "[DRY-RUN] kubectl -n $NS cp $ETC_TGZ $POD:/tmp/server-etc.tgz" + [[ -f "$DATA_TGZ" ]] && log "[DRY-RUN] kubectl -n $NS cp $DATA_TGZ $POD:/tmp/server-data.tgz" + log "[DRY-RUN] kubectl -n $NS exec $POD -- sh -lc 'set -e; [[ -f /tmp/server-etc.tgz ]] && tar -C / -xzf /tmp/server-etc.tgz; [[ -f /tmp/server-data.tgz ]] && tar -C / -xzf /tmp/server-data.tgz; rm -f /tmp/server-*.tgz'" + log "[DRY-RUN] kubectl -n $NS delete pod $POD" + continue + fi + + # Copy tarballs into the pod + [[ -f "$ETC_TGZ" ]] && kubectl -n "$NS" cp "$ETC_TGZ" "$POD":/tmp/server-etc.tgz + [[ -f "$DATA_TGZ" ]] && kubectl -n "$NS" cp "$DATA_TGZ" "$POD":/tmp/server-data.tgz + + # Extract in-place; paths inside tarballs are already absolute (/etc/... and /data/...) + kubectl -n "$NS" exec "$POD" -- sh -lc ' + set -e + [[ -f /tmp/server-etc.tgz ]] && tar -C / -xzf /tmp/server-etc.tgz || true + [[ -f /tmp/server-data.tgz ]] && tar -C / -xzf /tmp/server-data.tgz || true + rm -f /tmp/server-etc.tgz /tmp/server-data.tgz || true + # show result + ls -ld /etc/hyperledger/fabric-ca-server || true + ls -ld /data/hyperledger/fabric-ca-server || true + ' + + # Bounce the pod so CA re-reads files from disk + log "Restarting pod $POD to pick up restored data" + kubectl -n "$NS" delete pod "$POD" --wait=false >/dev/null 2>&1 || true + done + + log "Waiting for CA pods to become Ready..." + kubectl -n "$NS" wait --for=condition=Ready pod -l "$LABEL_SELECTOR" --timeout=180s || true +else + log "Skipping CA data restore (--no-data)" +fi + +log "✅ Restore completed." +