Incompatibility with Fabric CA 1.5.14+
Due updates related to the authentication on fabric ca service, now, we are unable to register identities using Python Fabric SDK.
In our case, we are using the Fabric Ansible Galaxy Collection for provisioning fabric network,
Error:
TASK [peer-organization-role : Register the organization admin] ****************
task path: /opt/app/playbooks/peer/peer-organization-role/tasks/create.yml:108
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: uwazi
<127.0.0.1> EXEC /bin/sh -c 'echo ~uwazi && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/uwazi/.ansible/tmp `"&& mkdir "` echo /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878 `" && echo ansible-tmp-1742423051.6323547-202-57634863004878="` echo /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878 `" ) && sleep 0'
Using module file /home/uwazi/.ansible/collections/ansible_collections/hyperledger/fabric_ansible_collection/plugins/modules/registered_identity.py
<127.0.0.1> PUT /home/uwazi/.ansible/tmp/ansible-local-39ur5wj1ab/tmpvhimgvgi TO /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878/AnsiballZ_registered_identity.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878/ /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878/AnsiballZ_registered_identity.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878/AnsiballZ_registered_identity.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/uwazi/.ansible/tmp/ansible-tmp-1742423051.6323547-202-57634863004878/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/modules/registered_identity.py", line 298, in main
identity_registered = connection.is_registered(registrar, enrollment_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/module_utils/certificate_authorities.py", line 284, in is_registered
return self._run_with_retry(lambda: self._is_registered(registrar, enrollment_id))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/module_utils/certificate_authorities.py", line 376, in _run_with_retry
raise e
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/module_utils/certificate_authorities.py", line 361, in _run_with_retry
result = func()
^^^^^^
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/module_utils/certificate_authorities.py", line 284, in <lambda>
return self._run_with_retry(lambda: self._is_registered(registrar, enrollment_id))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload_9nho7kmv/ansible_hyperledger.fabric_ansible_collection.registered_identity_payload.zip/ansible_collections/hyperledger/fabric_ansible_collection/plugins/module_utils/certificate_authorities.py", line 293, in _is_registered
raise CertificateAuthorityException(result['errors'][0]['code'], result['errors'][0]['message'])
fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"affiliation": "",
"api_authtype": "basic",
"api_endpoint": "https://fabric-console.government.xxxxx-local.test",
"api_key": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"api_secret": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"api_timeout": 60,
"api_token_endpoint": "https://iam.cloud.ibm.com/identity/token",
"attributes": [],
"certificate_authority": "ca",
"enrollment_id": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"enrollment_secret": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"hsm": null,
"max_enrollments": -1,
"registrar": "/opt/app/artifacts/wallet/ca-admin.json",
"state": "present",
"type": "admin"
}
},
"msg": "{'code': 20, 'message': 'Authentication failure'}"
}
The fabric CA respose when we try to register an identity:
2025/03/19 22:28:38 [INFO] 10.244.0.8:56746 GET /api/v1/identities/orgadmin?ca=ca 401 25 "Invalid token in authorization header: Token signature validation failed"
fabric-sdk-py appears to still use the old Fabric CA v1.3 authorization header format that requires a signature over request body and client cert.
Starting in Fabric CA v1.4 clients should update to the more secure authorization format that requires a signature over the HTTP method, path, request body, and client cert.
Fabric CA v1.4 through v1.5.13 tolerates the less secure v1.3 format with a compatibility mode by default. To make Fabric CA secure by default, starting in Fabric CA v1.5.14 if you want the old less secure compatibility mode you must enable it with environment variable FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3=true.
See the Fabric CA v1.5.14 release notes for more information.
The Java, Go, and Node SDK clients were updated to the new format back in 2019, but it looks like fabric-sdk-py never got updated to the more secure connection.
The fabric-sdk-py Fabric CA client auth header code that needs to be updated can be found here: https://github.com/hyperledger/fabric-sdk-py/blob/161eff3dff1cac299dfc0c4c20ca2a9f63dc606a/hfc/fabric_ca/caservice.py#L228-L241
For comparison, the fabric-operations-console Fabric CA client auth header was also recently updated to fix the same issue, see commit: https://github.com/hyperledger-labs/fabric-operations-console/commit/a403629875cd3491f9aa1592d6614edcbffe5be0
@denyeart Thanks. Specifically, whats was changed? Only the function:
function generateCaAuthToken(opts: { client_prv_key_b64pem: string, client_cert_b64pem: string, body_obj: any, path: string, method: string },
?
So, in fabric-sdk-py we should add the request path and the used http method for generating the token?
@denyeart Thanks. Specifically, whats was changed? Only the function:
function generateCaAuthToken(opts: { client_prv_key_b64pem: string, client_cert_b64pem: string, body_obj: any, path: string, method: string },?So, in fabric-sdk-py we should add the request path and the used http method for generating the token?
Yes. Let's see if we can get #198 to work.