Dynamic Attribute Provisioning Service

The TSG DAPS is an implementation of an IDS Dynamic Attribute Provisioning Service (DAPS) v2, combined with certificate authority capabilities to sign certificate signing requests (CSR).

The management interface is a multi-user interface that can set certification statuses for entries in the DAPS. Participants in the dataspace can login to the DAPS and make a Certificate Signing Request for themselves and a Component. The admin of the DAPS can verify the Participants and Component certificates, and grant them a Trust level. The Trust levels of Participants can be Entry, Member and Central. The Trust levels of Components are Base, Trust, and Trust+.

Initial support for federation of DAPS instances is included, by sharing JSON Web Key Sets of other DAPS instances to allow connectors connected to their primary DAPS to validate tokens of other DAPS instances by retrieving the public key of that remote DAPS from its primary DAPS. This feature is experimental.

Deployment

  • Download templates
    To deploy a DAPS, with a configuration with a Participant and a Connector in Kubernetes, you can follow the following steps. A tool that creates certificates and initial components can be used. For this, you need a configuration similar to the example available below. Create a new file in a new folder and paste the contents of the example below. Afterwards, edit the fields according to your needs. Make sure your terminal is open in the same folder for the next steps.
Click to expand example
# Global certificate details, used when no specific details are provided
global:
  # Certificate validity in years
  validityYears: 2
  # Country (Distinguished Name)
  country: NL
  # State or province (Distinguished Name)
  state: Groningen
  # Locality name (Distinguished Name)
  locality: Groningen
  # Organization (Distinguished Name)
  organization: Contoso
  # Organizational Unit (Distinguished Name)
  organizationalUnit: ICT
  # # Common Name (Distinguished Name)
  # commonName: Common Name
  # # Subject Alternative Names
  # subjectAlternativeNames:
  #   - localhost
  #   - root.ca.example.com

# Global contact information for DAPS entries
globalContact:
  name: John Doe
  emailAddress: john.doe@contoso.com

# Root CA certificate details, overrides fields in `global`
rootCa:
  # Common Name (Distinguished Name)
  commonName: IDS Test Root CA
  # Certificate validity in years
  validityYears: 8

# Device Sub CA certificate details, overrides fields in `global`
deviceSubCa:
  # Common Name (Distinguished Name)
  commonName: IDS Test Device Sub CA
  # Certificate validity in years
  validityYears: 4

# Participant Sub CA certificate details, overrides fields in `global`
participantSubCa:
  # Common Name (Distinguished Name)
  commonName: IDS Test Participants Sub CA
  # Certificate validity in years
  validityYears: 4

# DAPS configuration
daps:
  # DAPS Name
  name: DAPS
  # DAPS Kubernetes namespace, for producing README
  namespace: ids-ecosystem

# Participant configuration
participants:
  - # Participant identifier
    id: urn:ids:tsg:Test
    # Participant title
    title: TSG Test
    # # Contact details, overrides `globalContact`
    # contact:
    #   name: Maarten Kollenstart
    #   emailAddress: maarten.kollenstart@tno.nl

    # # Certificate details, overrides fields in `global`
    # certificate:
    #   subjectAlternativeNames:
    #     - localhost

    # # Path override, defaults to `participants/{title}`
    # path: certDirectory

    # # Certification level, one of: Entry, Member, Central (default)
    # level: Member
    # # Use existing pre-configured participant certificate
    # preConfiguredPEM:

# Connector configuration
connectors:
  - # Connector identifier
    id: urn:ids:tsg:connectors:MetadataBroker
    # Participant identifier
    participantId: urn:ids:tsg:TSG-Test
    # Connector title
    title: TSG Test Metadata Broker
    # # Contact details, overrides `globalContact`
    # contact:
    #   name: Maarten Kollenstart
    #   emailAddress: maarten.kollenstart@tno.nl

    # # Certificate details, overrides fields in `global`
    # certificate:
    #   subjectAlternativeNames:
    #     - localhost

    # # Path override, defaults to `connectors/{title}`
    # path: certDirectory

    # # Security profile, one of: Base (default), Trust, Trust+
    # securityProfile: Member

    # Kubernetes namespace
    namespace: ids-ecosystem

    # # Kubernetes secret name
    # secretName: ids-identity
  - # Connector identifier
    id: urn:ids:tsg:connectors:TestConnector
    # Participant identifier
    participantId: urn:ids:tsg:TSG-Test
    # Connector title
    title: TSG Test Connector
    # # Contact details, overrides `globalContact`
    # contact:
    #   name: Maarten Kollenstart
    #   emailAddress: maarten.kollenstart@tno.nl

    # # Certificate details, overrides fields in `global`
    # certificate:
    #   subjectAlternativeNames:
    #     - localhost

    # # Path override, defaults to `connectors/{title}`
    # path: certDirectory

    # # Security profile, one of: Base (default), Trust, Trust+
    # securityProfile: Member

    # Kubernetes namespace
    namespace: ids-connectors
    # Kubernetes secret name
    secretName: test-ids-identity-secret

  • Create Certificates

    helm repo add tsg https://nexus.dataspac.es/repository/tsg-helm
    helm repo update
    
    docker run -ti --rm -v $(pwd):/output docker.nexus.dataspac.es/tsg-pki-generator:main
    

You should now have a certificates folder containing a CA, SubCAs and Connector and Participant files.

To create the secrets that are necessary for the DAPS to function, execute the following commands:

  • Certificates
kubectl create secret generic \
    -n NAMESPACE \
    daps-identity \
    --from-file=daps.cert=./daps.cert \
    --from-file=daps.key=./daps.key \
    --from-file=cachain.cert=./cachain.cert

This requires the following file structure to be present:

.
├── cachain.cert            Certificate Authority Chain
├── daps.cert               DAPS Certificate
└── daps.key                DAPS Private Key
  • Certificate Authority secret
kubectl create secret generic \
    -n NAMESPACE \
    daps-ca \
    --from-file=devicesubca.cert=./devicesubca.cert \
    --from-file=devicesubca.key=./devicesubca.key \
    --from-file=participantsubca.cert=./participantsubca.cert \
    --from-file=participantsubca.key=./participantsubca.key

This requires the following file structure to be present:

.
├── devicesubca.cert        Device Sub CA Certificate
├── devicesubca.key         Device Sub CA Private Key
├── participantsubca.cert   Participant Sub CA Certificate
└── participantsubca.key    Participant Sub CA Private Key
  • (Optional) Initial Configuration
kubectl create configmap \
    -n NAMESPACE \
    daps-init \
    --from-file=participants.yaml=./participants.yaml \
    --from-file=components.yaml=./components.yaml \
    --from-file=federateddaps.yaml=./federateddaps.yaml

This following file structure must be present if all of the three yaml files are included:

.
├── participants.yaml       Initial participant configuration
├── components.yaml         Initial component (i.e. connector) configuration
└── federateddaps.yaml      Initial federated DAPS instances that are trusted

With everything setup in place, you are now ready to deploy the DAPS. For this, we need a configuration file like the example below. Change the values according to your needs. Every line with # in front should be updated.

Click to expand example
host: # Your DAPS URL, without 'https://'

issuer: # Issuer URL, This is the host with 'https://' in front

adminPassword: # BCRYPT encoded adminPassword

ingress:
  path: /(management.*|(v2/)?token|certs|(v2/)?.well-known/jwks.json)

emailValidation: "false"

mongodb:
  hostname: # MongoDB hostname
  username: # MongoDB user
  password: # MongoDB password

dapsUi:
  image: docker.nexus.dataspac.es/daps/generic-ui:master

With the values in place, we can now actually deploy the DAPS with the following commands. N.B. change the rootPassword to the password you set in the daps.values.yaml.

helm upgrade --install -n scsn-test-env mongodb bitnami/mongodb --version 13.9.4 --set auth.rootPassword=<your password> --set architecture=replicaset
helm upgrade --install -n NAMESPACE daps tsg/daps --version 1.1.2 -f values.daps.yaml

Setup

To start up a DAPS, you need to add some certificates for signing tokens and some certificates for signing other certificates.

For signing tokens, you need a DAPS_KEY, DAPS_CERT and CA_CHAIN. These files have default locations which are displayed below. The DAPS_CERT should be a X.509v3 certificate, DAPS_KEY the private key. CA_CHAIN shoud be the root certificate of the Certificate Authority.

For signing certificates, subCAs are needed. These files can be stored in the Sub CA Key & certificate locations for both the participants and the components.

Configuration

In the src/util/configuration.ts class all of the configurable properties are collected from environment variables and default locations, a summary of the environment variables that can be used:

Key Description Default
DAPS_KEY DAPS private key location /secrets/identity/daps.key
DAPS_CERT DAPS certificate location /secrets/identity/daps.cert
CA_CHAIN Certificate Authority chain location /secrets/identity/cachain.cert
INITIAL_COMPONENTS Initial components location /conf/components.yaml
INITIAL_PARTICIPANTS Initial participants location /conf/participants.yaml
INITIAL_FEDERATED_DAPS Initial federated DAPS location /conf/federateddaps.yaml
DEVICE_SUB_CA_KEY Device Sub CA key location /secrets/ca/devicesubca.key
DEVICE_SUB_CA_CERT Device Sub CA certificate location /secrets/ca/devicesubca.cert
PARTICIPANT_SUB_CA_KEY Participant Sub CA key location /secrets/ca/participantsubca.key
PARTICIPANT_SUB_CA_CERT Participant Sub CA certificate location /secrets/ca/participantsubca.cert
STRICT Strict validation of incoming client credentials true
ISSUER Issuer of the tokens, must be in line with the domain name the DAPS is hosted on nil
DAPS_FEDERATION Enable support for federated DAPS instances false
FEDERATION_INTERVAL DAPS federation JWKS refresh interval (in milliseconds) ‘86400000’
PROTOCOL Protocol used for the internal HTTP server (either http or https) http
ADMIN_PASSWORD BCrypt encoded administration password $2b$12$eJnNA51U6DEAfaZ3PzCK4uu3ILdPO7THZ17onYmJHnxRK5ly1pcJ2
MONGO_HOSTNAME MongoDB hostname nil
MONGO_PORT MongoDB port 27017
MONGO_USERNAME MongoDB username nil
MONGO_PASSWORD MongoDB password nil
MONGO_SSL_ENABLED MongoDB SSL connectivity false
EMAIL_VALIDATION Use email validation on the DAPS account creation true
TITLE Title of the DAPS as used in email communication TSG Identity Provider
DATASPACE Title of the dataspace, as used in email communication TSG Dataspace
LOGO Location of the logo for this DAPS size should be 600px wide, as used in email communication ${this.issuer}/logo.png
SMTP_SERVER SMTP Server for sending emails in-v3.mailjet.com
SMTP_PORT SMTP Server port for sending emails 465
SMTP_TLS SMTP TLS enabled for sending emails true
SMTP_USER Mailjet SMTP user for sending emails nil
SMTP_PASS Mailjet SMTP Secret key for sending emails nil
SMTP_FROM Mailjet SMTP E-mail address of the sender noreply@dataspac.es
AUTO_HANDLE_CERT_REQUESTS Automatically verify new certificates. N.B. only use in test environments. false

The initial state modifiers require valid YAML structures conformant to the respective model:

  • INITIAL_COMPONENTS: ComponentInternal[] (example at: example/conf/components.yaml)
  • INITIAL_PARTICIPANTS: ParticipantInternal[] (example at: example/conf/participants.yaml)
  • INITIAL_FEDERATED_DAPS: FederatedDAPSEntry[] (example at: example/conf/federateddaps.yaml)

HTTP Endpoints

The DAPS exposes the following HTTP endpoints:

General

Endpoint Method Request Response Description
(/v2)?/token POST DAT Token Request DAT Token Response Token request handler v2
/certs GET - { components: Component[], participants: Participant[] } Get the component and participant certificates
(/v2)?/.well-known/jwks.json GET issuer: Optional query parameter with federated DAPS identifier JSONWebKeySet Get the published public key in JSON WEb Key Set format.

Management

Endpoint Method Request Response Description
/management/register POST { email: string, password: string, name: string } - Handle registration request of a new user, with optionally email validation.
/management/forgotpassword POST { email: string} - Handle the request for the question to reset the password.
/management/resetpassword POST { email: string, currentPassword: string, newPassword: string} - Handle the request for resetting the password, either with the current password of the user or with a code that is received via email.
/management/verify GET code: Query parameter code, user: Query parameter username - Handle the verification of the email address, based on a code that has been sent via email.
/management/verifyuser PUT {code: string, user: string} - Manually verify the user, in case the email could not be sent.
/management/login POST {username: string, password: string} {user: User, token: string} Handle the login of the user and provide a token that can be used for further communication.
/management/users GET - User[] Retrieve a list of all users.
/management/users DELETE username: Query parameter username. - Delete a user, based on the query parameter username.
/management/users/updateRole PUT username: Query parameter username. - Update the role of a user.
/management/ca GET - CAChain configuration Handle the request for the CA chain used by this DAPS instance.
/management/participants GET - Participant[] Handle the request for participants, either only of the current user or all participants in case the current user is an admin.
/management/components GET - Component[] Handle the request for components, either only of the current user or all components in case the current user is an admin.
/management/participants POST {id: string, csr: string} {certificate: string} Create a new participant certificate based on a Certificate Signing Request and an identifier for the participant.
/management/components POST {participant: string, csr: string, name: string, id: string} {certificate: string} Create a new component cetificate based on a Certificate Signing Request and name, id, and participant.
/management/participants/{id} DELETE id: Query parameter for Participant id Delete the participant certificate.  
/management/components/{subject} DELETE subject: Query parameter for Component id Delete the component certificate.  
/management/participants/certify POST {participant: string, certify: string, level: string} - Set the certification for a given participant.
/management/components/certify POST {subject: string, certify: string, securityProfile: string} - Set the certification for a given component.
/management/federation GET - FederatedDAPSEntry[] Retrieve federated DAPS entries.
/management/federation POST {dapsid: string, url: string} FederatedDAPSEntry Set the certification for a given participant.
/management/federation DELETE id: Query parameter with the DAPS id. - Delete federated DAPS entry.
/management/federation PUT {id: string, url: string, trust: string} FederatedDAPSEntry Update federated DAPS entry.

Building locally

The Dynamic Attribute Provisioning Service is built via typescript & npm. First initialize the dependencies:

npm install

Compile the typescript files (in src) into javascript (in dist).

npm run tsc

The Gitlab CI configuration uses Kaniko to create the Docker image, but the Docker image can also be created manually via the Docker CLI:

docker build -t daps .

Didn't find what you were looking for?