-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create valid Gaia-X Credenials according to Gaia-X Tagus release #70
Comments
My first task will be to investigate DID, VCs and Gaia-X Compliance (defined by PRC Documnet in more detail and figure out, how these concepts relate to each other. I will document results of my investigations below. |
Here are the Key results of my investigations
A good starting point to play around with Gaia-X Credentials is Gaia-X Wizard offered by Gaia-X Lab. There is also a good tech theater, explaining the concepts behind Gaia-X on-boarding. |
Task 1: Implement DID generatorGaia-X Lab offers a DID generator. This generator supports did:web method specification only. There is also free python demo, how to generate DIDs. Additional python skeleton with respect to DID handling are published by Gaia-X Lab. I will have a closer look into these scripts... The first thing, we need is a public-private key pair and a x509 certificate (chain). According to Gaia-X Trust Framework, for development purpose let's encrypt is sufficent, in production, we need at least an eIDAS certificate or EV SSL certificate . I created a python script to generate did documents for a given DID. Files are stored in #88 and should be moved to its own repo. |
Task 2: Add cluster's and provider's DID to GX Credential GeneratorGaia-X uses DIDs to identity Participants (CSP) Service Offerings and Resources. Each CSP must have a DID and each SCS cluster offered as Service in Gaia-X needs a DID, too. These DIDs have to be placed in GX Credentials. SCS GX Credential Generator is configured by config file. I will place DIDs there. |
Task 3: Create Gaia-X compliant credential for CSP's and OpenStack cloudsGaia-X published an ontology containing several classes and attributes to describe CSP's and service's properties. Some of them are mandatory and not discoverable from Cloud. Furthermore, some properties must be provided in a temper.proof way as Verifiable Credential issued by a Gaia-X Clearing House. This is, e.g. the case for CSP's registration number. We have two options to handle these challenges
I go for option 1, first and limit data in configuration file to mandatory attributes of Legal Person (= GX Credential for CSP) and Service Offering. According to Trust Framework, these are:
Source code can be found in #89 ChallengesInconsistency of shapes in Gaia-X Clearing House and WG Service Characteristics GitLab Shapes used in Gaia-X Clearing House for verification and shapes published in WG Service Characteristics GitLab are not in sync. Gaia-X Clearing House is based on version 22.10, released in October 2022! A lot of concepts, required to describe IaaS offerings are not included in version 22.10. There will be an update in release "Loire", but its release date is not jet published. I summarized my investigations in bug reports within the appropriate Gaia-X repositories:
Misleading/Inconsistent definition of Gaia-X Credential Gaia-X dictates to publish all properties of CSPs and services as Gaia-X Credential. Gaia-X Credentials "... are W3C Verifiable Credentials with claims expressed in RDF [Gaia-X Architecture Framework, section Conceptual Model The same document says in section "Operating Model", "Gaia-X Self-Descriptions ... refers to a self-signed set of claims. This is equivalent to a Verifiable Credential where the holder is the issuer. In general, the term “Gaia-X Self Description” is replaced by “Gaia-X Credential”" [Architecture Document - section Operating Model] Wheres the first definition says a Gaia-X Credential is a Verifiable Credential, the second limits this to a Verifiable Credential, where the holder is the same entity as the issuer. IMO, both definitions are incorrect, as a Gaia-X Credential is a Verifiable Presentation, as defined by W3C. Furthermore, W3C VC Spec does allow several viable proof mechanisms. However, Gaia-X does not mention, which proof they prefer or support, giving the impression all viable proof mechanisms are supported. But this is not he case. I summarizes my findings in an issue waiting for clarification. Non-conform usage of Verifiable Credentials There is an example on how to create compliance Gaia-X Credentials in python. The example sets JSONWebSignature2020 as proof mechanism and uses the python library jwcrypto to create proof object. Gaia-X hashes credential and uses this hash as payload for calculation of signature. However, jwcrypto calculates hash for payload as input for signature, hence hash of hash is calculated. I neither know, if this is intended nor the side effects of this behavior. I opened an issue to raise this question. Gaia-X uses a compact serialization as JWS, which is a string consisting of protected header, payload and signature. However, Gaia-X omit payload part. Instead of Requesting and validating a VCSome Verifiable Credentials (VCs) are not created and signed locally by the CSP but an external entity. After receiving the response from the "https://registrationnumber.notary.lab.gaia-x.eu/v1/registrationNumberVC" Notary API, the included Using this certificate, the VC from the Notary API response can be cryptographically verified: notary_url = "https://registrationnumber.notary.lab.gaia-x.eu/v1/registrationNumberVC"
lrn_vc_id = "https://bakeup.io/lrn.json"
lrn_response = requests.post(notary_url + "?vcid=" + lrn_vc_id, ...)
lrn = lrn_response.json()
# Certificate used as public key to verify the JWS
# (this URL is part of the DID referenced in the response's proof object within the x5u field of
# the verificationMethod entry)
verification_cert_url = "https://registry.lab.gaia-x.eu/.well-known/x509CertificateChain.pem"
verify_credential(json.dumps(lrn), verification_cert_url) The import requests
import json
from jwcrypto import jwk, jws
# utils refers to https://gitlab.com/gaia-x/lab/workshops/gaia-x-101/-/blob/master/utils.py?ref_type=heads
from utils import sha256_normalized_vc, normalize
def verify_credential(credential_json_str, cert_url):
verifiable_credential = json.loads(credential_json_str)
# Retrieve the registry certificate which serves as the verification
# public key (JWK) for the JWS later
reg_cert_response = requests.get(cert_url)
if reg_cert_response.status_code != 200:
raise Exception(
f"Unable to retrieve verification certificate "
f"from: {cert_url}"
)
verification_cert_pem = reg_cert_response.text.encode('UTF-8')
verification_key = jwk.JWK.from_pem(verification_cert_pem)
# The proof object is part of the credential response, however
# it resembles JWS data applicable to the response without the
# proof object. Hence, we need to strip the proof object from
# the response.
proof = verifiable_credential.pop("proof")
# The remaining structure is the actual credential data that
# JWS was created for. The signature was applied to its
# normalized and hashed form, which we need to recreate here
# in order to verify the signature.
# See: https://w3c.github.io/vc-data-integrity/#how-it-works
normalized_credential = normalize(verifiable_credential)
hashed_credential = sha256_normalized_vc(normalized_credential)
# Instantiate a JWS object based on the jws attribute of the
# proof object, which contains a base64 representation of the JWS.
received_jws_token = jws.JWS()
received_jws_token.deserialize(proof["jws"])
# Finally, use the verification key (Gaia X registry public cert)
# and the hashed credential (which is the JWS' detached payload)
# in conjunction with the JWS token to verify the credential.
# This method will throw an exception if verification fails.
received_jws_token.verify(
verification_key,
detached_payload=hashed_credential.hexdigest()
) Bug in linkML's pyhton generatorGaia-X uses linkML to define Gaia-X Ontology. We use linkML's pyhton generator to create python classes for ontology. Several attributes of classes in Gaia-X ontology refers other classes. These, so called inlined objects will added to python object in special post initialization step via method |
Task 4: Put all credentials in a VP, sign it and retrieve Gaia-X Compliance CredentialRecap: technical prerequisitesThe following preparing steps must be taken.
Note: it is not required for the X.509 certificate from (3) used for proof verification to be issued for a Common Name (CN) matching any of the CSP's hosting domains or having any relation to the FQDN of the DID host. The only requirements for this certificate are:
Compliance process using Let's EncryptThe list of Gaia-X Trust Anchors1 points to Mozilla's included certificates2 which lists the Let's Encrypt root certificates, such as "ISRG Root X1". I created a setup for establishing a Provider Participant using Verifiable Credentials based on a Let's Encrypt certificate and key pair. I took most of the implementation from gaia-x-101.ipynb and adjusted the code where necessary. In short:
Using the process of gaia-x-101.ipynb I'm failing at the very last step:
About using Let's Encrypt certificates as trust anchorBased on a reported issue in the Gaia-X registry service3, it seems the above error happens when the Compliance API talks to the Registry API's trust anchors endpoint to verify the individual VC's certificate chains. Let's Encrypt (LE) produces three certificate files with
Directly checking any of the three files against the Gaia-X Registry API fails: sudo cp /etc/letsencrypt/live/gaia-x-testing.cloudandheat.com/fullchain.pem /srv/.well-known/cert.pem
curl -X POST -H "Content-Type: application/json" -d '''
{
"uri": "https://gaia-x-testing.cloudandheat.com/.well-known/cert.pem"
}''' https://registry.gaia-x.eu/v1/api/trustAnchor/chain/file
{"message":"Unable to validate certificate chain","error":"The parent certificate did not issue the given child certificate; the child certificate's issuer does not match the parent's subject.","statusCode":409} As such, the certificate chain generated by Including the LE's root certificateWhen accessing the webserver delivering the LE certificate using a browser such as Mozilla Firefox, a third certificate is added when downloading the certificate via the menu: the "ISRG Root X1" root certificate of Let's Encrypt. This certificate chain will consist of the following certificates:
The last certificate (root certificate) is missing from the chain file produced by # start building the certificate chain from the leaf certificate and R3 intermediate
sudo cat \
/etc/letsencrypt/live/gaia-x-testing.cloudandheat.com/cert.pem \
/etc/letsencrypt/live/gaia-x-testing.cloudandheat.com/chain.pem \
| sudo tee /srv/.well-known/fullchain.pem
# append the ISRG Root X1 (Let's Encrypt's root certificate)
curl -s \
https://crt.sh/?d=96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6 \
| sudo tee -a /srv/.well-known/fullchain.pem In your {
...
"verificationMethod": [
{
...
"publicKeyJwk": {
...
"x5u": "https://gaia-x-testing.cloudandheat.com/.well-known/fullchain.pem" Attempting to make a request to the Registry API of Gaia-X using the full chain now results in: curl -X POST -H "Content-Type: application/json" -d '''
{
"uri": "https://gaia-x-testing.cloudandheat.com/.well-known/fullchain.pem"
}''' https://registry.gaia-x.eu/v1/api/trustAnchor/chain/file
{"message":"Unable to validate certificate chain","error":"Certificate Root not found in trusted anchors","statusCode":409} At first that seems to contradict the official documentation on trust anchors1 where the "ISRG Root X1" is listed as included by Mozilla4 within the "Extended Validation (EV) Secure Sockets Layer (SSL)" category which is marked as "temporarily valid Trust Service Providers". However, the "v1" API of the Gaia-X Registry API only allows these root certificates in the context of EV SSL:
Let's Encrypt itself does not offer EV SSL certificates at all: https://letsencrypt.org/docs/faq/#what-services-does-let-s-encrypt-offer Using a development API version of the Gaia-X Registry API insteadAs stated in the issue3, the "v1" API version of the Gaia-X Registry does not accept certificates acquirable by mere mortals and strictly requires EIDAS or EV SSL certificates. Replacing the "registry.gaia-x.eu/v1/api/" by "registry.lab.gaia-x.eu/development/api/" as the target finally makes the request succeed (only if the full chain including the "ISRG Root X1" certificate as downloaded from the browser is present as explained above!): curl -X POST -H "Content-Type: application/json" -d '''
{
"uri": "https://gaia-x-testing.cloudandheat.com/.well-known/fullchain.pem"
}''' https://registry.lab.gaia-x.eu/development/api/trustAnchor/chain/file
{"result":true} As such, the Registry API is now accepting the LE certificate. Now after also redeploying the compliance_response = requests.post(
"https://compliance.lab.gaia-x.eu/development/api/credential-offers",
vp
)
Any previous error is now gone but the server runs into an unspecified error. Turns out that the "development" API environment is not stable enough but there is a "v1-staging"5 API path which serves as a middle ground: it does still accept Let's Encrypt certificates (unlike "v1") but does not run into internal 500 errors (unlike "development"). Conclusion
Footnotes
|
(content of this comment containing the LRN VC verification code sample has been merged into #70 (comment)) |
I added comments to both issues12. I think neither is actually a mistake. I can see some ambiguity regarding the double hashing topic but I lean towards the opinion that it is correctly implemented. The omitted payload seems perfectly valid according to an appendix of the referenced RFC specifying this exact behavior. Footnotes |
(content of this comment concerning the compliance process based on Let's Encrypt certificates has been merged into #70 (comment)) |
How to build a Gaia-X-compatible certificate chain from Let's Encrypt certbot filesSince certbot's files are not sufficient to build the full x5u-linked cert chain for the Gaia-X Compliance API (root certificate is missing), here's how to mix and match things to make it work without downloading the chain using a browser: # start building the certificate chain from the leaf certificate and R3 intermediate
sudo cat \
/etc/letsencrypt/live/gaia-x-testing.cloudandheat.com/cert.pem \
/etc/letsencrypt/live/gaia-x-testing.cloudandheat.com/chain.pem \
| sudo tee /srv/.well-known/fullchain.pem
# append the ISRG Root X1 (Let's Encrypt's root certificate)
curl -s \
https://crt.sh/?d=96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6 \
| sudo tee -a /srv/.well-known/fullchain.pem (assuming In your {
...
"verificationMethod": [
{
...
"publicKeyJwk": {
...
"x5u": "https://gaia-x-testing.cloudandheat.com/.well-known/fullchain.pem" Note: if changing/updating the key, don't forget to update your Note: the |
Mystery surrounding the Legal Registration Number (LRN)One part of the gaia-x-101.ipynb example is receving an externally signed VC for the LRN by making a request to This is a special case because:
Wait ... The request for acquiring a signed LRN VC requires a reference to an existing signed LRN VC JSON hosted by the provider? The request requires its own result? This looks like a chicken-and-egg problem. Where did this existing LRN VC come from? Let's look at the gaia-x-101.ipynb example. The LRN VC request generated by that example looks like this: {
...
"type": "gx:legalRegistrationNumber",
"id": "https://bakeup.io/lrn.json#cs",
...
} Looking at {
...
"type": [
"VerifiableCredential"
],
"id": "https://bakeup.io/lrn.json",
"issuer": "did:web:registration.lab.gaia-x.eu:v1",
"credentialSubject": {
...
"type": "gx:legalRegistrationNumber",
...
},
...
"proof": {
...
"verificationMethod": "did:web:registration.lab.gaia-x.eu:v1#X509-JWK2020",
...
}
} This hosted "Fake it till you make it" approachIf you don't have an existing LRN VC just pretend to: curl -s -o /dev/null -w "%{http_code}" \
https://gaia-x-testing.cloudandheat.com/.well-known/lrn.json
404 The file does not exist. We can request a VC for it anyway: {
"@context": [
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/participant"
],
"type": "gx:legalRegistrationNumber",
"id": "https://gaia-x-testing.cloudandheat.com/.well-known/lrn.json#cs",
"gx:vatID": "..."
} ... and we get a valid signed VC that is accepted in a VP later on by the Complianca API (I tested this). DID not working for LRN request idThe above only works with the plain URL like also used in the gaia-x-101.ipynb example. It does not work if we use a {
"@context": [
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/participant"
],
"type": "gx:legalRegistrationNumber",
"id": "did:web:gaia-x.eu:legalRegistrationNumber.json",
"gx:vatID": "FR79537407926"
} (example taken from the Notary API documentation) This will work for the LRN request at first but not for the Compliance API request later on as this one will try to resolve the DID reference. Such a DID reference will not properly resolve:
If we change to DID to point to our server via "
It tries to find a Conclusion From the research above I conclude the following for now:
However, this does not really make sense to me yet so I filed an issue about this matter. Footnotes |
I just figured out, that Mozilla Firefox is doing the job for you. If you download Let's encrypt certificate chain via Mozilla Firefox, you also get a certificate chain accepted by [Gaia-X Registry in deployment version1. However, this a very unstable deployment of Gaia-X Registry for LOIRE release (v2) Footnotes |
I was finally able to reproduce lessons learned found out by @markus-hentsch and received an valid Gaia-X Credential from Compliance Service. I will integrate this in to GX Credential Generator now, see #96 |
Wrong evaluation of id of credential subject of Gaia-X Credential of VatIDGaia-X requires each legal person to have a valid registration number, which is attested by GXDCH Notary Service. To receive a Gaia-X Credential for vatID, you have to provide three parameters: (1) vatID, (2) credentialSubjet id and (3) credential id Using DE281093504 as vatID, did:web:gaia-x.cloudandheat.com as credential subject id and https://gaia-x.cloudandheat.com as credential id, we receive the following Gaia-X Credential {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"type": [
"VerifiableCredential"
],
"id": "https://gaia-x.cloudandheat.com/lrn.json",
"issuer": "did:web:registration.lab.gaia-x.eu:v1-staging",
"issuanceDate": "2024-06-24T19:44:01.096Z",
"credentialSubject": {
"@context": "https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#",
"type": "gx:legalRegistrationNumber",
"id": "did:web:gaia-x.cloudandheat.com",
"gx:vatID": "DE281093504",
"gx:vatID-countryCode": "DE"
},
"evidence": [
{
"gx:evidenceURL": "https://ec.europa.eu/taxation_customs/vies/services/checkVatService",
"gx:executionDate": "2024-06-24T19:44:01.096Z",
"gx:evidenceOf": "gx:vatID"
}
],
"proof": {
"type": "JsonWebSignature2020",
"created": "2024-06-24T19:44:01.111Z",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:web:registration.lab.gaia-x.eu:v1-staging#X509-JWK2020",
"jws": "eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..bWuYiFhg1yS4RAiEx45z8wLMZY8kyMvt49GjKCYcLFYmIXE6iPipp8j0MuMChX9MIcHXkDP2pk-yqi4ofsnWu5kaFqO_vYrhF5YmGSr0TSK5SCNkEdfFqz94zXz_nLy1uDzHwLMpEaHzXNvIESEGKuD44SOJo_JE9Jlkha-VPL-4K_8ogBIUAZ-sW2wWnncZ_4YLRLy59oCNxl7h_6IrJ3gyRLl5YYWheg9xRrkUbvIh4F5fs6O3H2oqDvLYuKiZT-0cfG_Z0QplUWV_jywqn1RBVatFUqx6xVlLSLijTzmYWDcYDUxwaefa2RCL7pTJQtOt8Pm2Fvi9sGPqegf5-g"
}
} Putting this into Verifiable Presentation for Legal Person results in the following json file {
"@context":"https://www.w3.org/2018/credentials/v1",
"type":"VerifiablePresentation",
"verifiableCredential":[
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"credentialSubject":{
"@context":"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#",
"gx:vatID":"DE281093504",
"gx:vatID-countryCode":"DE",
"id":"did:web:gaia-x.cloudandheat.com",
"type":"gx:legalRegistrationNumber"
},
"evidence":[
{
"gx:evidenceOf":"gx:vatID",
"gx:evidenceURL":"https://ec.europa.eu/taxation_customs/vies/services/checkVatService",
"gx:executionDate":"2024-06-24T19:46:59.092Z"
}
],
"id":"https://gaia-x.cloudandheat.com/lrn.json",
"issuanceDate":"2024-06-24T19:46:59.092Z",
"issuer":"did:web:registration.lab.gaia-x.eu:v1-staging",
"proof":{
"created":"2024-06-24T19:46:59.103Z",
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..GYUliHQiwvLpPhTulDgjTU6DBgftyW98UiFAJbjvGO7o2ia6Bf2QrwdayXqqrYL4UUhY-u3RRIlTv3hSR224uuB8U5kIs5dGLfX6GXmuWYem2DSdlreDm6PMR5LTrRnOId4FJTNYeqzWakR9EAz7dM2G3mRhDRooLz1v_SDM9FSCvFCaKgZj6eofOTXmpEoSPijHUfgbhmOIjGF3R9YxAedRTVEpQwmb5Z_rg7vmAAQMfQAZnV7Fe0bz2LKh7vLl9Gq5wNYPmRwhBEMFr6vjWYCbrjdQq2V_NaeicZgd1ptSwODqjpo_TfMBD56MeZPGSkV87GPGSHCN_tNN3IwiHA",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:registration.lab.gaia-x.eu:v1-staging#X509-JWK2020"
},
"type":[
"VerifiableCredential"
]
},
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#"
],
"credentialSubject":{
"gx:termsAndConditions":"The PARTICIPANT signing the Self-Description agrees as follows:\n- to update its descriptions about any changes, be it technical, organizational, or legal - especially but not limited to contractual in regards to the indicated attributes present in the descriptions.\n\nThe keypair used to sign Verifiable Credentials will be revoked where Gaia-X Association becomes aware of any inaccurate statements in regards to the claims which result in a non-compliance with the Trust Framework and policy rules defined in the Policy Rules and Labelling Document (PRLD).",
"id":"did:web:gaia-x.cloudandheat.com",
"type":"gx:GaiaXTermsAndConditions"
},
"id":"https://gaia-x.cloudandheat.com/tandc.json",
"issuanceDate":"2024-06-24T19:46:56.537466+00:00",
"issuer":"did:web:gaia-x.cloudandheat.com",
"proof":{
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..XXEENN6BG6F23shRsnsgLIsOnvGyAC-1YhRAUTSBfJ9cSex_UZT8WwT5LVApfZpJe798RHlPA7DpGOVNODUFuKdaex45abxZrhUn8WewszaUhILeXzeops7ESHpsFYC6JiL1l14ISeMLhoej48mC-0MwssPavXY8oXnqyYzalxcb4P2kCg7Z6GadjGeZPlChDvM0m9r1tyPAQHbn5GI1Rvi7QfLS5wVRgwvukJmpdz765EYceofNfi2cZv8rIUXzA_HA3vZE5vmFnKVO5V3Af3U-D3Diy_19OG7CdSp3kWnhOsyAJHikMGWNhUAKBIa7spAopG5-A2v7PaFknjor0rjRqld1Vz4FsEQUhTjxBsVs9d-cEDUQr1FbMNbl_crkA3_XerOZUZgQT3tHu-4QMbmteDm6Y1gbHEpoq_ZHH5NJqZziKEiH23zZ_8FfOMAuQGwu3SITWRxyr9kT5djvgWcO_IkpCCGFpxPEJ43tjCz46wZUTL7PkQurkK-_bHCYIFwCbotxTm7cO14IuNwv7XnxSJozg-lFC-Ya8lOO00Ivoz8LOXsNw8i5ZFUJfKyP0FWT91fQ5MwAhd0UDNfe9LQeFbzCpNQ4DS1CVOKzUWU477o279h0OFty7UNeqedzEL8PSxrfSW-9DYlAN3Lh5ieX5oayoZCXqDWtj9WXOoQ",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:gaia-x.cloudandheat.com#JWK2020-X509-2"
},
"type":"VerifiableCredential"
},
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#"
],
"credentialSubject":{
"gx:headquarterAddress":{
"gx:countrySubdivisionCode":"DE-SN"
},
"gx:legalAddress":{
"gx:countrySubdivisionCode":"DE-SN"
},
"gx:legalName":"Cloud\u0026Heat Technologies GmbH",
"gx:legalRegistrationNumber":{
"id":"https://gaia-x.cloudandheat.com/lrn.json"
},
"id":"did:web:gaia-x.cloudandheat.com",
"type":"gx:LegalParticipant"
},
"id":"https://gaia-x.cloudandheat.com/legal_person.json",
"issuanceDate":"2024-06-24T19:46:59.153346+00:00",
"issuer":"did:web:gaia-x.cloudandheat.com",
"proof":{
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..cuFuO6jokK9U23IBE-oPP2kjCU0N-iKykl4hqIijz1NSyCrT-864qv_271z2vK9_U5q6zakSeDfRrcpAFI5_VfOD5ldRpo_g-q8L42GouA3832N760xFSlVKKze5jmsXiaJFte3xGBWDkunyMqh7Rs1JBxUrQrei2fdMm9fEnNh9tchfBEqBekgjdcMa_fSRf9BizerB8U_PON1M-040Ruf8WWKmcye-c_lgAYRYfCUUOE9ONBoMSeroWwQMlM-InaXaLvFPDo2KTUyEi6P6ot4P41aPinYxY9ruYpRDSSjFEQ5QeFw9zMGnu7H7U7ajb2jBnkFjhl1NWjY-meKWNj0CIC8caMx6wR-2NMs-Z-SRvSRRRT3Ff-gKy3Bs7HqKO0tkCls_qN-RXiqgVut025KsL_O_0NAgbIGhzZRywSz_KNClCwz9G7Is_lxn7c4lZUh6MH0f3y9hCqweyjyRuvU8s_fbUv_t71XatiwtwToEd3a5Hmgr6xOAw6j-wjVFgRfRGTg-EwmANWUlp3KZ6tAI9wIMru-h-2wUYwjtEjmZa9dEBu4_XCFzmmnAyNsaKAXUUd-FDRRU9nMBVASz4RHxOMQaMlxxn1hPNFq31t0ALHzOMEPn9CBgcI0XiDONAfqdZiNkB0h4jGt0rPE0OZJw1MYK-9UcXegojScVjP8",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:gaia-x.cloudandheat.com#JWK2020-X509-2"
},
"type":"VerifiableCredential"
}
]
} Sending Verifiable Presentation to Compliance Service, receive in the following error: {
"statusCode": 409,
"message": {
"conforms": false,
"results": [
"ERROR: did:web:gaia-x.cloudandheat.com https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#legalRegistrationNumber: Value does not have shape <https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#legalRegistrationNumberShape>; DETAILS: https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#taxID: Less than 1 values; https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#EUID: Less than 1 values; https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#EORI: Less than 1 values; null: At least one of taxID, vatID, EUID, EORI or leiCode must be defined.;"
]
},
"error": "Conflict"
} Compliance Service is complaining about missing registration number of Legal Person. But this is not true. Legal Person is identified by did However, if you replace DID ( {
"@context":"https://www.w3.org/2018/credentials/v1",
"type":"VerifiablePresentation",
"verifiableCredential":[
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1"
],
"credentialSubject":{
"@context":"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#",
"gx:vatID":"DE281093504",
"gx:vatID-countryCode":"DE",
"id":"https://gaia-x.cloudandheat.com/lrn.json",
"type":"gx:legalRegistrationNumber"
},
"evidence":[
{
"gx:evidenceOf":"gx:vatID",
"gx:evidenceURL":"https://ec.europa.eu/taxation_customs/vies/services/checkVatService",
"gx:executionDate":"2024-06-24T19:56:38.006Z"
}
],
"id":"https://gaia-x.cloudandheat.com/lrn.json",
"issuanceDate":"2024-06-24T19:56:38.006Z",
"issuer":"did:web:registration.lab.gaia-x.eu:v1-staging",
"proof":{
"created":"2024-06-24T19:56:38.017Z",
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..lI0ksxCie07Hyhs9sOOiV1EMnl3H_aG2TqnZo-sSzNeG6H36ulUegjNypeEx-zErTCBQfaEm8Pk-BcyR0Z9ScsTEYOn_qYBsPS5qdwoqaBlsJQqkEcLAABb8dLYx0CZdbP0T9Hn6xsSPDnUmHWAGGSOucZbZSbwkl34HmkbKWjhfSG7_RQwQUxbedk2DhiJkPIO_kXosVWVnP3QKjrvdBl24xw6HgeqmvkOIn0kma7gngogl5vaB9e9ideE6eiOX4QDiEyRPUdlAhHvM3Fox5LL0mCi_pNqd9lWjSDmSo5qPh3dsfT6XXJQRe1O2w5l5Gu2KatdinWffn1cDtRpE0A",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:registration.lab.gaia-x.eu:v1-staging#X509-JWK2020"
},
"type":[
"VerifiableCredential"
]
},
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#"
],
"credentialSubject":{
"gx:termsAndConditions":"The PARTICIPANT signing the Self-Description agrees as follows:\n- to update its descriptions about any changes, be it technical, organizational, or legal - especially but not limited to contractual in regards to the indicated attributes present in the descriptions.\n\nThe keypair used to sign Verifiable Credentials will be revoked where Gaia-X Association becomes aware of any inaccurate statements in regards to the claims which result in a non-compliance with the Trust Framework and policy rules defined in the Policy Rules and Labelling Document (PRLD).",
"id":"did:web:gaia-x.cloudandheat.com",
"type":"gx:GaiaXTermsAndConditions"
},
"id":"https://gaia-x.cloudandheat.com/tandc.json",
"issuanceDate":"2024-06-24T19:56:35.083545+00:00",
"issuer":"did:web:gaia-x.cloudandheat.com",
"proof":{
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..U3PQiW-xcjK9UdvEtDlrCkqSrGsfrOsxCTAedHkhqI-hA3GxcrBq9JSEk-fT3kfXbxFLTnkSNBMdsC-5gVFNkGWh0XhMD90NbNnTn-6HnS0BoCf0BaPiZQP2S4NgY5nzfYjfKcM_F4ouht2rIYJNd-ouUBCKT7CErqdANa8MjNoZNNvCkBo_jE6swroXRM0lDLwuA5kLcXVuxnND8Y7fw5npx5h1Xqx1zfODy-mQ2eMySmZlMAkTCBi_876F-Xdsto60U1Od5jnxP9HSJjU230cKukdNanVvuuK5JGDLit4NTjRymAcddagNF5duzW_yEc9zehI977I6Suwiq1tXvNVPI54xb6CYS3v9xROxM70F28GG6KERwhbj0HdiQAoVPeiis27ekVOVxVKIs4x4LemMyDBR36QVBUb-hTLrkiu2-UynhE75WDScl7c0q1lpoyjTZqxQqOQreW7mKmvwf02fPULNl2NjJquWPHOzg4FCWj4T5yEm7hi7h2xzdS6pIx188ePH0YpBBh5kNzCyJ3Tii6_fcHXhg8uSSMGLJWtLbDZLclf0zdJne4fSMqi4zgKzvD3NjpEiXNOxXOkWvR9Efw-7Wl8zgzunqINplDP80vkGCiT33gOTetoA6iMzu8FIkfrnlHp8dTC_lTZEfyNt5Rzkq2sRmDakNI3SVUY",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:gaia-x.cloudandheat.com#JWK2020-X509-2"
},
"type":"VerifiableCredential"
},
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#"
],
"credentialSubject":{
"gx:headquarterAddress":{
"gx:countrySubdivisionCode":"DE-SN"
},
"gx:legalAddress":{
"gx:countrySubdivisionCode":"DE-SN"
},
"gx:legalName":"Cloud\u0026Heat Technologies GmbH",
"gx:legalRegistrationNumber":{
"id":"https://gaia-x.cloudandheat.com/lrn.json"
},
"id":"did:web:gaia-x.cloudandheat.com",
"type":"gx:LegalParticipant"
},
"id":"https://gaia-x.cloudandheat.com/legal_person.json",
"issuanceDate":"2024-06-24T19:56:38.130480+00:00",
"issuer":"did:web:gaia-x.cloudandheat.com",
"proof":{
"jws":"eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..U5uEoVY-9Nnc8DIvFH1m5shQuGv7eCY33lJvnbzDKL8RHVAZTksov6Skgv0UXsGXJqh_5joabY1O3Vn3mPQLt3JSogQC9jDjT2DZboiVmkvRyu4nWhKHM9WzwsbzZEAxZeJQxtpIdCWAhXB4zluSkKgvf8BFtndPvK_rWf255QeAozI4FEhE8ZTWnGjSR4JVfSWumc29v9qcuETEvbXVJ0KPyf9QbRGYXj_GCZZj78mtrSyardj32FX6BhOWvEiVQltEsqVMmyZiPmq13tKT1HCCOhUkkxzS-l_-_ZUzrBLTb-KdV5mFm8fWWjt6wPMor9SJnyAG7w9lahKS-hZy0QJxDjjQRc2VDMZnVC27zbO0ecqTajU4FTyaYPFCO24tGsGCvL7Qv2GE51mWqzc7xMFmTPJPjEOM-5KeKQH8u65Nw7YC8nc5okk1o_og1UUbWH-K6sb4z8lRa43y8mtrTOW24r0u0ynNIJt6xKws7N1kKCHKZulpuevnrEIgIv4VzTx6VZ_xLbby_TxS5qu9Ztj4YfZnNxHnxgVgNyPSJPRp8a_kYmUfGTCbJ66-P2490xV1s46Tdq1lfT1oWE8D-Hzl2EDXgAy1tp1goyYx-ng3XRKshiPUK_LpDOBHAn6aIHWiiTifOlj25ZMRPZLFkTieYGxmekH0kvxDnkOZ3F0",
"proofPurpose":"assertionMethod",
"type":"JsonWebSignature2020",
"verificationMethod":"did:web:gaia-x.cloudandheat.com#JWK2020-X509-2"
},
"type":"VerifiableCredential"
}
]
} Answer from Gaia-X Compliance Service
The only difference between invalid request and a valid one is the value of credential subject of Gaia-X Credential for vatID. Instead of DID |
EDIT: on closer inspection they are separate observations after all. Your observation in a nutshell (as I understand it):
So the question is what the intended purpose of the This seems related to the conversation with the Gaia-X devs that I had here: https://gitlab.com/gaia-x/lab/compliance/gaia-x-notary-registrationnumber/-/issues/5#note_1940639707 From the documentation:
I infer two key points from this:
I did some more research and testing on this and I think the problem is the following:
It works for me with the following example VP: {
"@context": "https://www.w3.org/2018/credentials/v1",
"type": "VerifiablePresentation",
"verifiableCredential": [
{
// The LRN VC
"id": "did:does:not:matter",
"credentialSubject": {
"gx:vatID": "DE281093504",
"id": "did:local:my-bogus-id", // !!!
"type": "gx:legalRegistrationNumber"
},
},
{
// The LegalParticipant VC
"credentialSubject": {
"gx:legalRegistrationNumber": {
"id": "did:local:my-bogus-id" // !!!
},
"id": "https://gaia-x-testing.cloudandheat.com/.well-known/participant.json",
"type": "gx:LegalParticipant"
},
"id": "https://gaia-x-testing.cloudandheat.com/.well-known/participant.json",
}
]
} (JSON truncated to the relevant bits) Note that I'm setting an unresolvable bogus DID reference ( Conclusion:
|
@anjastrunk I created some figures about my learnings above for the blog post as these learnings are also relevant and very important to integrate in the post in my opinion. The LRN credential and its two different identifiers:I have noticed that some examples such as the gaia-x-101 workshop or https://bakeup.io/lrn.json use a trick to specify a URL to the VC for both identifiers while not violating the rule to keep identifiers unique: {
"id": "https://bakeup.io/lrn.json",
"credentialSubject": {
"id": "https://bakeup.io/lrn.json#cs",
}
} They use a non-destructive The identifier relation between LRN and Participant credential:As already mentioned, my testing confirmed that neither of the identifiers have to be URLs. They can be local identifiers as long as both VCs (LRN, Participant) are part of the same VP. The only requirement is for the subject identifier of the LRN VC to match the legalRegistrationNumber identifier reference in the Participant VC. |
Obtaining an eIDAS certificate as an organizationContext:
The EU provides a dashboard where eIDAS provider can be discovered at https://eidas.ec.europa.eu/efda/tl-browser/#/screen/home Providers can be searched by offering type and location using https://eidas.ec.europa.eu/efda/tl-browser/#/screen/search/type/1 Relevant offering types are certificates intended either for "electronic signature" (ESig), "electronic seal" (ESeal) or which are defined3 as follows:
This suggests that as an organization (legal person), the only choice would be ESeal.
... where eIDAS Regulation (EU) No 910/20144 says:
The current implementation of the Gaia-X Registry API5, which is responsible for checking the trust anchors, does not seem to differentiate between ESig and ESeal providers and only aggregates all eligible eIDAS providers from the official trusted lists. This does indeed seem to confirm that ESig by a natural person representing the organization (legal person) would be sufficient for signing Verifiable Credentials as an organization being a participant of Gaia-X. At the time of writing, the Deutsche Telekom Security GmbH currently offers a qualified eIDAS signing certificate (ESig) based on a Smartcard with 2 year validity called "Qualified.ID Light"6 for 83,19€. eIDAS Qualified Website Authentication Certificate (QWAC)I created an issue at the Gaia-X repositories asking for clarification on whether both ESig and ESeal are accepted equally and was made aware of a third type: Qualified Website Authentication Certificate (QWAC). At the time of writing, only 4 German providers are listed on the eIDAS Trust Service Search to offer QWACs and none of the links provided refer to an actual offering. In contrast to eIDAS ESig and ESeal products I'm unable to find reliable information on any direct offering of QWACs to purchase and whether those are distinct products or a property of or extension to existing certificate types (e.g. SSL). eIDAS alternative: EV SSL certificatesBesides eIDAS, EV SSL issuers are also accepted trust anchors. EV SSL certificates are still SSL certificates at their core so they can also be used for an organization's web presence simultaenously just like any other SSL certificate whereas the eIDAS ESig and ESeal cannot and would be limited to eIDAS use cases only. As such, an EV SSL certificate is much more versatile. Due to the fact that it represents the highest grade of an SSL certificate in terms of trustworthiness, this could also be considered an upgrade to an organization's web presence if used as web SSL certificate in addition to representing the public key of Gaia-X Credentials. However, this versatility comes at a cost: these certificates usually cost a few hundred Euros per year9, making them notably more expensive than eIDAS certificates on average. Footnotes
|
I was finally able to create a Gaia-X compliant credential for an OpenStack cloud. However, as Tagus release does not support In order to still publish detailed properties on OpenStack Cloud, we will publish a separate VC not confirmed by Compliance Service. As soon as Loire is released, we will update generator. |
Wired usage of 'id' field in credentialSubjectAccording to W3C standard of Verifiable Credentials, of
However, Gaia-X uses update from 19.08.24: Gaia-X agree to my trust concerns documented in #78, but does neither propose a solution nor mention a date to fix this. IMO and to the best of my knowledge fixing to undermine trust is a important and emergent issue, which is not rocket science to fix. I will propose my bugfix in #78. |
GX Credential Generator generates one huge json-ld file with ALL information about SCS cluster, currently. In favor to flexibility and maintenance, each credential should be serialized in its own file and referenced by its DID in other credentials.
This issue contains two tasks:
LegalPerson
and compliant credential for OpenStack cloud asVirtualMachineServiceOffering
- 70 support did in generated gaia x credentials #88Figure out how GX Credential can be retrieved from a given DID.--> moved to a separate issue (Link Gaia-X Credentials with each other #102 ), for now, all credentials are in one file.The text was updated successfully, but these errors were encountered: