Error - "Too many intermediates for path length constraint" when register new identity - hyperledger-fabric

In hyperledger fabric-ca, I create chain of CAs like:
Root CA - Intermediate CA 1 - Intermediate CA 2 - Intermediate CA 3
With these CAs, in "signing" part of fabric-ca-config.yaml file I set "maxpathlen:5", and in "csr" part I set "pathlength:5"
It's mean my chain is valid for at least 4 Intermediate CA and I can register new identity in Intermediate CA 3.
In fact, I can enroll admin of Intermediate CA 3, however, when I register new identity, I have this error:
/register 401 26 "Untrusted certificate: Failed to verify certificate: x509: too many intermediates for path length constraint"
What wrong I have done, and how to config this value
My config file
# Version of config file
version: 1.1.0
# Server's listening port (default: 7054)
port: 7054
# Enables debug logging (default: false)
debug: false
# Size limit of an acceptable CRL in bytes (default: 512000)
crlsizelimit: 512000
tls:
# Enable TLS (default: false)
enabled: false
# TLS for the server's listening port
certfile:
keyfile:
clientauth:
type: noclientcert
certfiles:
ca:
# Name of this CA
name:
# Key file (is only used to import a private key into BCCSP)
keyfile:
# Certificate file (default: ca-cert.pem)
certfile:
# Chain file
chainfile:
crl:
# Specifies expiration for the generated CRL. The number of hours
# specified by this property is added to the UTC time, the resulting time
# is used to set the 'Next Update' date of the CRL.
expiry: 24h
registry:
# Maximum number of times a password/secret can be reused for enrollment
# (default: -1, which means there is no limit)
maxenrollments: -1
# Contains identity information which is used when LDAP is disabled
identities:
- name: Admin
pass: adminpw
type: client
affiliation:
attrs:
hf.Registrar.Roles: "*"
hf.Registrar.DelegateRoles: "*"
hf.Revoker: true
hf.IntermediateCA: true
hf.GenCRL: true
hf.Registrar.Attributes: "*"
hf.AffiliationMgr: true
affiliations:
org1:
- department1
- department2
org2:
- department1
signing:
default:
usage:
- digital signature
expiry: 8760h
profiles:
ca:
usage:
- cert sign
- crl sign
expiry: 43800h
caconstraint:
isca: true
maxpathlen: 5
tls:
usage:
- signing
- key encipherment
- server auth
- client auth
- key agreement
expiry: 8760h
csr:
cn: fabric-ca-server
names:
- C: US
ST: "California"
L:
O: Hyperledger
OU: Fabric
hosts:
- ca
- localhost
ca:
expiry: 131400h
pathlength: 5

I found the root cause is simple because when initialize network, I don't create cert/key by myself and config it so that Fabric-CA use itself key/cert which config default set maxpathlen=1.
If I create cert/key by myself and in cert config pathlength > 3 then my network will be ok.

Related

can't enroll peer to hyperledger fabric on aks using hlf operator

I keep getting this error when trying to enroll a peer to the fabric ca via the hlf operator:
Error: enroll failed: enroll failed: Failed to read response of request: POST >http://org1-ca.domain.com/enroll
{"hosts":null,"certificate_request":"-----BEGIN CERTIFICATE REQUEST----->\nMIHxMIGYAgEAMBExDzANBgNVBAMTBmVucm9sbDBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABBQob4jvqjE/>E6OZPuKQdPUNw+SMXCI6FtPI3j0rPqxGu9DrnCgasGG\nzop5KWFZrMFL/JrbKfm2+GPrRPrLyjWgJTAjBgkqhki>G9w0BCQ4xFjAUMBIGA1Ud\nEQQLMAmCB0JVSDAwOTcwCgYIKoZIzj0EAwIDSAAwRQIhALWFAahmDd+lmQdkqSgI>n7M5m+BeFz8fZBzrDVbcbrVzCAiAsThJfkxEdNwm1AQ45KUqT0hDfnHQCAUK0Fjp5\n6IaPPQ==\n-----END >CERTIFICATE REQUEST-----\n","profile":"","crl_override":"","label":"","NotBefore":"0001->01-01T00:00:00Z","NotAfter":"0001-01-01T00:00:00Z","ReturnPrecert":false,"CAName":""}: >unexpected EOF
I'm using the hlf operator by hyperledger fabric on an aks cluster with application gateway + nginx ingress for the routing / externalDNS for name resolution within an Azure dns zone.
Here is my fabric-ca.yaml:
apiVersion: hlf.kungfusoftware.es/v1alpha1
kind: FabricCA
metadata:
creationTimestamp: null
name: org1-ca
namespace: fabric
spec:
affinity: null
ca:
affiliations: null
bccsp:
default: SW
sw:
hash: SHA2
security: "256"
ca: null
cfg:
affiliations:
allowRemove: true
identities:
allowRemove: true
crl:
expiry: 24h
csr:
ca:
expiry: 131400h
pathLength: 0
cn: ca
hosts:
- localhost
- org1-ca.domain.io
names:
- C: US
L: ""
O: Hyperledger
OU: North Carolina
ST: ""
intermediate:
parentServer:
caName: ""
url: ""
name: ca
registry:
identities:
- affiliation: ""
attrs:
hf.AffiliationMgr: true
hf.GenCRL: true
hf.IntermediateCA: true
hf.Registrar.Attributes: '*'
hf.Registrar.DelegateRoles: '*'
hf.Registrar.Roles: '*'
hf.Revoker: true
name: enroll
pass: enrollpw
type: client
max_enrollments: -1
signing: null
subject:
C: ES
L: Alicante
O: Kung Fu Software
OU: Tech
ST: Alicante
cn: ca
tlsCa: null
clrSizeLimit: 512000
cors:
enabled: false
origins: []
db:
datasource: fabric-ca-server.db
type: sqlite3
debug: false
env: null
hosts:
- localhost
- org1-ca
- org1-ca.fabric
- org1-ca.domain.io
image: hyperledger/fabric-ca
imagePullSecrets: null
istio:
metrics:
provider: prometheus
statsd:
address: 127.0.0.1:8125
network: udp
prefix: server
writeInterval: 10s
resources:
limits:
cpu: 300m
memory: 256Mi
requests:
cpu: 10m
memory: 128Mi
rootCA:
subject:
C: California
L: ""
O: Hyperledger
OU: Fabric
ST: ""
cn: ca
service:
type: ClusterIP
serviceMonitor: null
storage:
accessMode: ReadWriteOnce
size: 1Gi
storageClass: default
tlsCA:
affiliations: null
bccsp:
default: SW
sw:
hash: SHA2
security: "256"
ca: null
cfg:
affiliations:
allowRemove: true
identities:
allowRemove: true
crl:
expiry: 24h
csr:
ca:
expiry: 131400h
pathLength: 0
cn: tlsca
hosts:
- localhost
- org1-ca.domain.io
names:
- C: US
L: ""
O: Hyperledger
OU: North Carolina
ST: ""
intermediate:
parentServer:
caName: ""
url: ""
name: tlsca
registry:
identities:
- affiliation: ""
attrs:
hf.AffiliationMgr: true
hf.GenCRL: true
hf.IntermediateCA: true
hf.Registrar.Attributes: '*'
hf.Registrar.DelegateRoles: '*'
hf.Registrar.Roles: '*'
hf.Revoker: true
name: enroll
pass: enrollpw
type: client
max_enrollments: -1
signing: null
subject:
C: ES
L: Alicante
O: Kung Fu Software
OU: Tech
ST: Alicante
cn: tlsca
tlsCa: null
tolerations: null
version: 1.4.9
here is the command I'm passing to the operator to enroll the peer identity and create the MSP
kubectl hlf ca register --name=org1-ca --user=peer --secret=peerpw --type=peer --enroll-id=enroll --enroll-secret=enrollpw --mspid=Org1MSP --namespace=fabric --ca-url=org1-ca.domain.io
Any help would be greatly appreciated!!
Please check if you are able to do telnet over ca host. Looks like you are using some different host. I don't see your host in the CA Custom Resource. Please verify the configuration once.

Hyperledger fabric facing difficult setting up intermediate CA

I am trying to create intermediate CA for my project, I have one root CA and one intermediate CA with Intermediate CA config file as shown below. I am facing issue to create keypairs/MSP and tls cert for intermediate CA & unable to pass the config file to intermediate CA. Steps I followed
Running the Root CA container with bootstrapping admin.
Enrol the admin which generate the MSP for CA admin for org1
fabric-ca-client enroll -u https://admin:adminpw#localhost:7054 --caname ca-org1 --tls.certfiles ${PWD}/organizations/fabric-ca/org1/tls-cert.pem
Register the Intermediate CA to root CA using below command
fabric-ca-client register --caname ca-org1 --id.name ica --id.attrs '"hf.Registrar.Roles=user,peer",hf.Revoker=true,hf.IntermediateCA=true' --id.secret icapw --tls.certfiles ${PWD}/organizations/fabric-ca/org1/tls-cert.pem
Run the Intermediate CA container as shown below with using the below config file.
Enrol the Intermediate CA
fabric-ca-client enroll -u https://icaadmin:icaadminpw#localhost:6054 --caname ica-org1 --tls.certfiles ${PWD}/organizations/fabric-ca/icaOrg1/tls-cert.pem
Root CA
version: "2"
networks:
test:
services:
ca_org1:
image: hyperledger/fabric-ca:$IMAGE_TAG
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org1
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_CA_SERVER_PORT=7054
ports:
- "7054:7054"
command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
volumes:
- ../organizations/fabric-ca/org1:/etc/hyperledger/fabric-ca-server
container_name: ca_org1
networks:
- test
Intermidate CA
version: "2"
networks:
test:
services:
ica-org1:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ica-org1
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_LOGGING_SPEC=debug
- FABRIC_CA_SERVER_PORT=6054
ports:
- "6054:6054"
command: sh -c 'fabric-ca-server start -b icaadmin:icaadminpw -u -d http://ica:icapw#ca-org1:7054'
volumes:
- ../organizations/fabric-ca/icaOrg1:/etc/hyperledger/fabric-ca-server
container_name: ica-org1
networks:
- test
ICA Fabric Config file
# Version of config file
version: 1.2.0
# Server's listening port (default: 7054)
port: 7054
# Enables debug logging (default: false)
debug: false
# Size limit of an acceptable CRL in bytes (default: 512000)
crlsizelimit: 512000
tls:
# Enable TLS (default: false)
enabled: true
# TLS for the server's listening port
certfile:
keyfile:
clientauth:
type: noclientcert
certfiles:
ca:
# Name of this CA
name: ica.org1.example.com
# Key file (is only used to import a private key into BCCSP)
keyfile:
# Certificate file (default: ca-cert.pem)
certfile:
# Chain file
chainfile:
crl:
# Specifies expiration for the generated CRL. The number of hours
# specified by this property is added to the UTC time, the resulting time
# is used to set the 'Next Update' date of the CRL.
expiry: 24h
registry:
# Maximum number of times a password/secret can be reused for enrollment
# (default: -1, which means there is no limit)
maxenrollments: -1
# Contains identity information which is used when LDAP is disabled
identities:
- name: icaadmin
pass: icaadminpw
type: client
affiliation: ""
attrs:
hf.Registrar.Roles: "client,peer,user,member"
hf.Registrar.DelegateRoles: "client,peer,user,member"
hf.Revoker: true
hf.IntermediateCA: true
hf.GenCRL: true
hf.Registrar.Attributes: "*"
hf.AffiliationMgr: true
db:
type: sqlite3
datasource: fabric-ca-server.db
tls:
enabled: false
certfiles:
client:
certfile:
keyfile:
ldap:
# Enables or disables the LDAP client (default: false)
# If this is set to true, the "registry" section is ignored.
enabled: false
# The URL of the LDAP server
url: ldap://<adminDN>:<adminPassword>#<host>:<port>/<base>
# TLS configuration for the client connection to the LDAP server
tls:
certfiles:
client:
certfile:
keyfile:
# Attribute related configuration for mapping from LDAP entries to Fabric CA attributes
attribute:
names: ["uid", "member"]
converters:
- name:
value:
maps:
groups:
- name:
value:
affiliations:
org1:
- department1
- department2
signing:
default:
usage:
- digital signature
expiry: 8760h
profiles:
ca:
usage:
- cert sign
- crl sign
expiry: 43800h
caconstraint:
isca: true
maxpathlen: 0
tls:
usage:
- signing
- key encipherment
- server auth
- client auth
- key agreement
expiry: 8760h
csr:
cn: ica.org1.example.com
names:
- C: US
ST: "North Carolina"
L: "Durham"
O: org1.example.com
OU:
hosts:
- localhost
- org1.example.com
ca:
expiry: 131400h
pathlength: 1
#############################################################################
# BCCSP (BlockChain Crypto Service Provider) section is used to select which
# crypto library implementation to use
#############################################################################
bccsp:
default: SW
sw:
hash: SHA2
security: 256
filekeystore:
# The directory used for the software file-based keystore
keystore: msp/keystore
cacount:
cafiles:
intermediate:
parentserver:
url: https://ca-org1:7054
caname: ca.org1.example.com
enrollment:
hosts: localhost
profile:
label:
tls:
certfiles:
client:
certfile:
keyfile:
Since you configured your CAs as TLS enabled, root TLS certificate must be used by intermediate CA. Check your intermediate CA file's corresponding section.
The certfiles attribute's value /tmp/root-ca-cert.pem is the same file of root CA's file: /tmp/hyperledger/fabric-ca/crypto/ca-cert.pem
intermediate:
parentserver:
url: https://admin:admin#root.ca.example.com:7054
caname: root.ca.example.com
enrollment:
hosts:
- ca1.example.com
profile: ca
label:
tls:
certfiles:
- /tmp/root-ca-cert.pem
client:
certfile:
keyfile:

Hyperledger fabric Failed to submit transaction: Error: No endorsement plan available for {"chaincodes":[{"name":"fabcar"}]}

I am using the hyperledger fabric network using the basic network from fabric sample. Basic network consist of one orderer and one peer. I have install the fab car chain code in network and join the channel.Please suggest me how to add Endorsement policy to chaincode, Below are command i used to initiate the chain code
1. peer chaincode install -n fabcar -p github.com/ -v 1.1
2. peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -c '{"Args":[]}' -n fabcar -v 1.1 -P "OR('Org1MSP.peer','Org1MSP.admin','Org1MSP.member')"
I am using the fabric sdk for query the fabcar it works well. But if i try to invoke chaincode its give me error stating
Failed to submit transaction: Error: No endorsement plan available for {"chaincodes":[{"name":"fabcar"}]}
config Tx
Organizations:
# SampleOrg defines an MSP using the sampleconfig. It should never be used
# in production but may be used as a template for other definitions
- &OrdererOrg
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: OrdererOrg
# ID to load the MSP definition as
ID: OrdererMSP
# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: crypto-config/ordererOrganizations/example.com/msp
- &Org1
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org1MSP
# ID to load the MSP definition as
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org1.example.com
Port: 7051
Application: &ApplicationDefaults
# Organizations is the list of orgs which are defined as participants on
# the application side of the network
Organizations:
Orderer: &OrdererDefaults
# Orderer Type: The orderer implementation to start
# Available types are "solo" and "kafka"
OrdererType: solo
Addresses:
- orderer.example.com:7050
# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 2s
# Batch Size: Controls the number of messages batched into a block
BatchSize:
# Max Message Count: The maximum number of messages to permit in a batch
MaxMessageCount: 10
# Absolute Max Bytes: The absolute maximum number of bytes allowed for
# the serialized messages in a batch.
AbsoluteMaxBytes: 99 MB
# Preferred Max Bytes: The preferred maximum number of bytes allowed for
# the serialized messages in a batch. A message larger than the preferred
# max bytes will result in a batch larger than preferred max bytes.
PreferredMaxBytes: 512 KB
Kafka:
# Brokers: A list of Kafka brokers to which the orderer connects
# NOTE: Use IP:port notation
Brokers:
- 127.0.0.1:9092
# Organizations is the list of orgs which are defined as participants on
# the orderer side of the network
Organizations:
Profiles:
OneOrgOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
OneOrgChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
crypto-config
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer
Domain: example.com
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: Org1
Domain: org1.example.com
Template:
Count: 1
Users:
Count: 1
Invoke function
async function Invoke(userwallet,usename,channelName,chaincodeName) {
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(userwallet);
if (!userExists) {
console.log('An identity for the user "user1" does not exist in the wallet');
console.log('Run the registerUser.js application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: usename, discovery: { enabled: true, asLocalhost: true} });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork(channelName);
// Get the contract from the network.
const contract = network.getContract(chaincodeName);
// Submit the specified transaction.
// createCar transaction - requires 5 argument, ex: ('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom')
// changeCarOwner transaction - requires 2 args , ex: ('changeCarOwner', 'CAR10', 'Dave')
await contract.submitTransaction('createCar','CAR12', 'Honda', 'Accord', 'Black', 'Tom');
//await contract.submitTransaction('changeCarOwner', 'CAR10', 'Dave');
console.log('Transaction has been submitted');
// Disconnect from the gateway.
await gateway.disconnect();
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
module.exports.Invoke = Invoke
It is weird, Let's do some trial and error
Try to make changes in the below snippet. This removes the policy do not worry a default policy will be applicable
peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -c '{"Args":[]}' -n fabcar -v 1.1

How to use getAttributeValue() in ClientIdentity for fabric shim?

I am using nodejs sdk for hyperledger fabric, inside my chaincode i need to get name of the identity (sam) who is execting the transaction.
{"name":"sam","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"5aad871581d63447218743ee79289c0c6f531a032d3cf1f0be32083e8c0cbaea","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICizCCAjGgAwIBAgIUQq0tPLPFsLujCsRclZc9POmAh6EwCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTkxMTE5MDU0ODAwWhcNMjAxMTE4MDU1\nMzAwWjBAMTAwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMBIGA1UECxMLZGVw\nYXJ0bWVudDExDDAKBgNVBAMTA3NhbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA\nBGbtyGsC9QNBlO0Z5sumDzEaYR4m8GJpXW2f8Qlvjt79IzCWDjGwFePAIOfnUojz\naDbr0VHgpnWOtUIKUqTVPOujgdUwgdIwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB\n/wQCMAAwHQYDVR0OBBYEFCR78iTBbBSCYjxajhOMyYrWDO8iMCsGA1UdIwQkMCKA\nIHWD+xHmJ7l80nLYW67w4+Bftya5oeDfD9d4KXfnqn3NMGYGCCoDBAUGBwgBBFp7\nImF0dHJzIjp7ImhmLkFmZmlsaWF0aW9uIjoib3JnMS5kZXBhcnRtZW50MSIsImhm\nLkVucm9sbG1lbnRJRCI6InNhbSIsImhmLlR5cGUiOiJjbGllbnQifX0wCgYIKoZI\nzj0EAwIDSAAwRQIhAJcIBDcygI6Z67ueo46b3WnJCZr+D1HzhaWNp6Lj/+7oAiA6\nRRc9JjnWFvaFaqIJTyNaE7/HFXTXKr+HIkig/UEZpQ==\n-----END CERTIFICATE-----\n"}}}
I have used the below code
async approve(ctx) {
try {
const owId = new clientIdentity(ctx.stub).getAttributeValue('name')
return owId.toString();
} catch(error) {
console.log(error);
throw new Error(`Low on amount`);
}
}
but the above code is not returning the name or any other attributes.
Help will be appreciated!!!
The attributes you retrieve with getAttributeValue() in the Smart Contract are created as follows with the command line:
fabric-ca-client register --id.name clare --id.secret hursley1 --id.maxenrollments -1 --id.attrs 'department=Finance:ecert,location=Berkshire:ecert'
So I'm creating 2 attributes for department and location. Note the :ecert on the end which means that I want the attributres written to the certificate, not just stored in the CA database. Note also that the attributes aren't added to existing certificates, but only "appear" when you have enrolled or renrolled.
Using the node SDK this is a snippet of code that would add the department attribute when registering an Identity:
//create user attr array
let registerAttrs = [];
let registerAttribute = {
name: "department",
value: "Finance",
ecert: true
};
registerAttrs.push(registerAttribute);
// at this point we should have the admin user
// first need to register the user with the CA server
return fabric_ca_client.register(
{
enrollmentID: username,
affiliation: "org1",
role: "client",
attrs: registerAttrs
},
admin_user
);
In your smart contract you can then access the attribute:
ctx.clientIdentity.getAttributeValue('department');
Note that with the fabric-contract-api the clientIdentity object is already populated so you don't need a new clientIdentity object.
You have no attribute named "name". If you analyze your X.509 certificate...
openssl x509 -text -noout -in yourcert.pem
...you get...
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
42:ad:2d:3c:b3:c5:b0:bb:a3:0a:c4:5c:95:97:3d:3c:e9:80:87:a1
Signature Algorithm: ecdsa-with-SHA256
Issuer: C = US, ST = California, L = San Francisco, O = org1.example.com, CN = ca.org1.example.com
Validity
Not Before: Nov 19 05:48:00 2019 GMT
Not After : Nov 18 05:53:00 2020 GMT
Subject: OU = client + OU = org1 + OU = department1, CN = sam
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:66:ed:c8:6b:02:f5:03:41:94:ed:19:e6:cb:a6:
0f:31:1a:61:1e:26:f0:62:69:5d:6d:9f:f1:09:6f:
8e:de:fd:23:30:96:0e:31:b0:15:e3:c0:20:e7:e7:
52:88:f3:68:36:eb:d1:51:e0:a6:75:8e:b5:42:0a:
52:a4:d5:3c:eb
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
24:7B:F2:24:C1:6C:14:82:62:3C:5A:8E:13:8C:C9:8A:D6:0C:EF:22
X509v3 Authority Key Identifier:
keyid:75:83:FB:11:E6:27:B9:7C:D2:72:D8:5B:AE:F0:E3:E0:5F:B7:26:B9:A1:E0:DF:0F:D7:78:29:77:E7:AA:7D:CD
1.2.3.4.5.6.7.8.1:
{"attrs":{"hf.Affiliation":"org1.department1","hf.EnrollmentID":"sam","hf.Type":"client"}}
Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:97:08:04:37:32:80:8e:99:eb:bb:9e:a3:8e:
9b:dd:69:c9:09:9a:fe:0f:51:f3:85:a5:8d:a7:a2:e3:ff:ee:
e8:02:20:3a:45:17:3d:26:39:d6:16:f6:85:6a:a2:09:4f:23:
5a:13:bf:c7:15:74:d7:2a:bf:87:22:48:a0:fd:41:19:a5
Your attribute keys are:
hf.Affiliation
hf.EnrollmentID
hf.Type
There is no "name" attribute. You are probably looking for "hf.EnrollmentID".
EDIT: You yourself indicated your certificate in your question, in enrollment.identity.certificate field. I have only saved...
-----BEGIN CERTIFICATE-----
MIICizCCAjGgAwIBAgIUQq0tPLPFsLujCsRclZc9POmAh6EwCgYIKoZIzj0EAwIw
czELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh
biBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT
E2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTkxMTE5MDU0ODAwWhcNMjAxMTE4MDU1
MzAwWjBAMTAwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMBIGA1UECxMLZGVw
YXJ0bWVudDExDDAKBgNVBAMTA3NhbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BGbtyGsC9QNBlO0Z5sumDzEaYR4m8GJpXW2f8Qlvjt79IzCWDjGwFePAIOfnUojz
aDbr0VHgpnWOtUIKUqTVPOujgdUwgdIwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB
/wQCMAAwHQYDVR0OBBYEFCR78iTBbBSCYjxajhOMyYrWDO8iMCsGA1UdIwQkMCKA
IHWD+xHmJ7l80nLYW67w4+Bftya5oeDfD9d4KXfnqn3NMGYGCCoDBAUGBwgBBFp7
ImF0dHJzIjp7ImhmLkFmZmlsaWF0aW9uIjoib3JnMS5kZXBhcnRtZW50MSIsImhm
LkVucm9sbG1lbnRJRCI6InNhbSIsImhmLlR5cGUiOiJjbGllbnQifX0wCgYIKoZI
zj0EAwIDSAAwRQIhAJcIBDcygI6Z67ueo46b3WnJCZr+D1HzhaWNp6Lj/+7oAiA6
RRc9JjnWFvaFaqIJTyNaE7/HFXTXKr+HIkig/UEZpQ==
-----END CERTIFICATE-----
...as yourcert.pem to check it via openssl.

Different certificate chain order when using Node's HTTPS/TLS vs. OpenSSL s_client

I'm trying to parse the certificate chain using Node's HTTPS request. I'm testing it on npmjs.com (not www.npmjs.com). When I test it on OpenSSL, it shows me that the chain is in the incorrect order.
openssl s_client -connect npmjs.com:443 -showcerts
OpenSSL Response First Certificate
subject: /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
issuer: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
Next Certificate ->
subject: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
issuer: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
Next Certificate ->
subject: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
issuer: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
However, when I go to step through the certificate chain using my Node's HTTPS request, when the socket is emitted and I do
socket.getPeerCertificate(true)
the chain is in the correct order and I'm getting one different certificate on the Node request than I am on the openssl request.
Node's Response First Certificate:
subject
{ OU:
[ 'GT40876434',
'See www.rapidssl.com/resources/cps (c)14',
'Domain Control Validated - RapidSSL(R)' ],
CN: '*.npmjs.com' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
Next Certificate ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
Next Certificate ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
Why is this happening?
It looks like node is reordering the certificates for returning in getPeerCertificates so that they reflect the correct order in the trust chain (*). But in reality the certificates are in the wrong order, as can be seen by openssl s_client and also in the analysis of SSLLabs:
Chain issues Incorrect order
(*) the relevant code in node-4.5.0 (LTS) is in src/node_crypto.cc function void SSLWrap<Base>::GetPeerCertificate. There it retrieves the leaf certificate and the original peer certificates from the openssl library using SSL_get_peer_certificate (leaf certificate) and SSL_get_peer_cert_chain (chain). It then does not return the certificates in the original chain order but scans through the chain and adds the certificates in the order how they are depend on each other by checking with X509_check_issued.
This way it returns the certificates in proper dependency order instead of the original order as send by the peer. It also automatically skips any certificates which don't belong in the chain.
It will also add the issuer of the certificate even if it is not contained it the chain (which it usually isn't). This way you not only get a different order of certificates as seen in your example but actually different certificates. The server sends the following certificates in this order:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[B] /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, issued by Equifax
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
But getPeerCertificate returns the following:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
[R] CA/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, self-signed
Thus certificate [B] will not be included but instead certificate [R] which is the root certificate contained in the trust store. Both have the same subject and key, but are signed by different entities. [B] is signed by Equifax while [R] is self-signed.

Resources