Skip to content

Commit

Permalink
Added support for couchdb jwt authentication in peer
Browse files Browse the repository at this point in the history
Signed-off-by: Aviral Agrawal <aviral.agrawal@dltlabs.io>
  • Loading branch information
aviralagrawalDLT committed Dec 16, 2022
1 parent bebb75f commit 8cfb6b6
Show file tree
Hide file tree
Showing 110 changed files with 3,045 additions and 6 deletions.
61 changes: 61 additions & 0 deletions core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"time"
"unicode/utf8"

"github.com/golang-jwt/jwt"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/core/ledger"
"github.com/pkg/errors"
Expand Down Expand Up @@ -205,6 +206,11 @@ type couchDoc struct {
attachments []*attachmentInfo
}

type JWT struct {
privateKey []byte
publicKey []byte
}

func (d *couchDoc) key() (string, error) {
m := make(jsonValue)
if err := json.Unmarshal(d.jsonValue, &m); err != nil {
Expand Down Expand Up @@ -1707,6 +1713,10 @@ func (couchInstance *couchInstance) handleRequest(ctx context.Context, method, d
if couchInstance.conf.Username != "" && couchInstance.conf.Password != "" {
//req.Header.Set("Authorization", "Basic YWRtaW46YWRtaW5w")
req.SetBasicAuth(couchInstance.conf.Username, couchInstance.conf.Password)
} else if couchInstance.conf.JwtPrivateKey != "" && couchInstance.conf.JwtPublicKey != "" {
// Token generation service logic
token := generateToken(couchInstance.conf.JwtPrivateKey, couchInstance.conf.JwtPublicKey, couchInstance.conf.JwtUserName)
req.Header.Add("Authorization", "Bearer "+token)
}

//Execute http request
Expand Down Expand Up @@ -1882,3 +1892,54 @@ func printDocumentIds(documentPointers []*couchDoc) (string, error) {
}
return strings.Join(documentIds, ","), nil
}

func NewJWT(privateKey []byte, publicKey []byte) JWT {
return JWT{
privateKey: privateKey,
publicKey: publicKey,
}
}

func (j JWT) Create(ttl time.Duration, jwtUserName string) (string, error) {
key, err := jwt.ParseRSAPrivateKeyFromPEM(j.privateKey)
if err != nil {
return "", fmt.Errorf("create: parse key: %w", err)
}

now := time.Now().UTC()

claims := make(jwt.MapClaims)
claims["_couchdb.roles"] = []string{"_admin"}
claims["exp"] = now.Add(ttl).Unix() // The expiration time after which the token must be disregarded.
claims["alg"] = "RS256"
claims["sub"] = jwtUserName // Couchdb Server Admin user name

token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key)
if err != nil {
return "", fmt.Errorf("create: sign token: %w", err)
}

fmt.Println(token)

return token, nil
}

func generateToken(privateKeyPath string, publicKeyPath string, jwtUserName string) string {
prvKey, err := ioutil.ReadFile(privateKeyPath)
if err != nil {
log.Fatalln(err)
}
pubKey, err := ioutil.ReadFile(publicKeyPath)
if err != nil {
log.Fatalln(err)
}

jwtToken := NewJWT(prvKey, pubKey)

// 1. Create a new JWT token.
token, err := jwtToken.Create(time.Duration(24) * time.Hour, jwtUserName)
if err != nil {
log.Fatalln(err)
}
return token
}
4 changes: 4 additions & 0 deletions core/ledger/ledger_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type StateDBConfig struct {

// CouchDBConfig is a structure used to configure a CouchInstance.
type CouchDBConfig struct {
//JWT Authentication support
JwtPrivateKey string
JwtPublicKey string
JwtUserName string
// Address is the hostname:port of the CouchDB database instance.
Address string
// Username is the username used to authenticate with CouchDB. This username
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/frankban/quicktest v1.9.0 // indirect
github.com/fsouza/go-dockerclient v1.4.1
github.com/go-kit/kit v0.8.0
github.com/golang-jwt/jwt v3.2.0+incompatible
github.com/golang/protobuf v1.3.3
github.com/golang/snappy v0.0.2 // indirect
github.com/google/go-cmp v0.5.0 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
Expand Down Expand Up @@ -92,6 +93,8 @@ github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-jwt/jwt v3.2.0+incompatible h1:cy0jZQ1aewnxirUHoalEYhE2zxzE7JqR9YQPWhEKzXc=
github.com/golang-jwt/jwt v3.2.0+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand Down
3 changes: 3 additions & 0 deletions internal/peer/node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ func ledgerConfig() *ledger.Config {

if conf.StateDBConfig.StateDatabase == "CouchDB" {
conf.StateDBConfig.CouchDB = &ledger.CouchDBConfig{
JwtPrivateKey: viper.GetString("ledger.state.couchDBConfig.jwtPrivateKey"),
JwtPublicKey: viper.GetString("ledger.state.couchDBConfig.jwtPublicKey"),
JwtUserName: viper.GetString("ledger.state.couchDBConfig.jwtUserName"),
Address: viper.GetString("ledger.state.couchDBConfig.couchDBAddress"),
Username: viper.GetString("ledger.state.couchDBConfig.username"),
Password: viper.GetString("ledger.state.couchDBConfig.password"),
Expand Down
16 changes: 10 additions & 6 deletions sampleconfig/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -265,18 +265,18 @@ peer:
clientAuthRequired: false
# X.509 certificate used for TLS server
cert:
file: tls/server.crt
file: ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
# Private key used for TLS server (and client if clientAuthEnabled
# is set to true
key:
file: tls/server.key
file: ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/keystore/ecdb62013c3a8fa3d01c7bc05dbfff01e128c633bc714928e9ba317436557898_sk
# Trusted root certificate chain for tls.cert
rootcert:
file: tls/ca.crt
file: ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
# Set of root certificate authorities used to verify client certificates
clientRootCAs:
files:
- tls/ca.crt
- ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
# Private key used for TLS when making client connections. If
# not set, peer.tls.key.file will be used instead
clientKey:
Expand Down Expand Up @@ -325,7 +325,7 @@ peer:
Security:

# Path on the file system where peer will find MSP local configurations
mspConfigPath: msp
mspConfigPath: ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp

# Identifier of the local MSP
# ----!!!!IMPORTANT!!!-!!!IMPORTANT!!!-!!!IMPORTANT!!!!----
Expand Down Expand Up @@ -623,11 +623,15 @@ ledger:
# Limit on the number of records to return per query
totalQueryLimit: 100000
couchDBConfig:
# For JWT authentication support
jwtPrivateKey: ../cert/id_rsa
jwtPublicKey: ../cert/id_rsa.pub
jwtUserName: test
# It is recommended to run CouchDB on the same server as the peer, and
# not map the CouchDB container port to a server port in docker-compose.
# Otherwise proper security must be provided on the connection between
# CouchDB client (on the peer) and server.
couchDBAddress: 127.0.0.1:5984
couchDBAddress: 10.25.54.85:5984
# This username must have read and write authority on CouchDB
username:
# The password is recommended to pass as an environment variable
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAERilj/4dz/nKAAj2FuOWOxxtWAS4FhGWL
8Ao+yaFnf0zPMMQFOJY2+F4kPEULk9pMoczFfh0aVxTl5D73mCeEXj83HCOblUr5
2MkEe/KuiF0ZBnZAkYcbqBgnpBfqrJRI
-----END PUBLIC KEY-----
14 changes: 14 additions & 0 deletions sampleconfig/organizations/fabric-ca/org1/ca-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICFzCCAb2gAwIBAgIUMxpBQuf3mSucXgRUaoLyhH3KoMgwCgYIKoZIzj0EAwIw
aDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK
EwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMt
Y2Etc2VydmVyMB4XDTIyMTAwMzEwMzEwMFoXDTM3MDkyOTEwMzEwMFowaDELMAkG
A1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQKEwtIeXBl
cmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMtY2Etc2Vy
dmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUmsIx/XvXwVLI7fqHScMVjhw
mgT9Dli1ZWEwRURRXAfTE/OaMXXc3q0LVcVnP3DWJwnzDD7WZ9ZTGDXZBsj4CaNF
MEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
FAUbq6uhCgGQ7TOgRT4m+K8pV0OzMAoGCCqGSM49BAMCA0gAMEUCIQDAV2DX3Jt4
e4pHA2Q7pO/WXzO4vi/w6woJKGk0gxF+JwIgTf1y6omHpne4ulxTHTGjLdhFlruy
G6nGPJdWWeMP2gg=
-----END CERTIFICATE-----
Loading

0 comments on commit 8cfb6b6

Please sign in to comment.