Giter Club home page Giter Club logo

nuts-foundation / nuts-node Goto Github PK

View Code? Open in Web Editor NEW
21.0 5.0 14.0 33.12 MB

The reference implementation of the Nuts specification. A decentralized identity network based on the w3c ssi concepts with practical functionality for the healthcare domain.

Home Page: https://nuts-foundation.gitbook.io

License: GNU General Public License v3.0

Go 96.90% Shell 1.81% Makefile 0.22% Dockerfile 0.05% Standard ML 0.01% HTML 0.92% Smarty 0.07% JavaScript 0.02%
did decentralized-identifiers verifiable-credentials vc pki

nuts-node's Introduction

nuts-node

Open-source implementation of did:web, OpenID4VC, PEX, private key management and related logic. It enables secure and trusted data exchange between organizations. It contains all the necessary components for secure discovery and authorization.

See the documentation for how to set up, integrate and use the Nuts node.

Build Status

Documentation Status

Code coverage

Maintainability

Build Docker images

Nuts Community on Slack

Development

GitHub go.mod Go version or higher is required.

Building

Just use go build.

ES256 Koblitz support

To enable ES256K (Koblitz) support, you need to build with the jwx_es256k tag:

go build -tags jwx_es256k

Building for exotic environments

You can build and run the Nuts node on more exotic environments, e.g. Raspberry Pis:

  • 32-bit ARMv6 (Raspberry Pi Zero): env GOOS=linux GOARCH=arm GOARM=6 go build

Running tests

Tests can be run by executing

go test ./...

Code Generation

Code generation is used for generating mocks, OpenAPI client- and servers, and gRPC services. Make sure that GOPATH/bin is available on PATH and that the dependencies are installed

Install protoc:

MacOS: brew install protobuf
Linux: apt install -y protobuf-compiler

Install Go tools:

make install-tools

Generating code:

To regenerate all code run the run-generators target from the makefile or use one of the following for a specific group

Group Command
Mocks make gen-mocks
OpenApi make gen-api
Protobuf + gRCP make gen-protobuf
All make run-generators

README

The readme is auto-generated from a template and uses the documentation to fill in the blanks.

make gen-readme

Documentation

The documentation can be build by running the following command from the /docs directory:

make html

Configuration

The Nuts node can be configured using a YAML configuration file, environment variables and commandline params.

The parameters follow the following convention: $ nuts --parameter X is equal to $ NUTS_PARAMETER=X nuts is equal to parameter: X in a yaml file.

Or for this piece of yaml

nested:
    parameter: X

is equal to $ nuts --nested.parameter X is equal to $ NUTS_NESTED_PARAMETER=X nuts

Config parameters for engines are prepended by the engine.ConfigKey by default (configurable):

engine:
    nested:
        parameter: X

is equal to $ nuts --engine.nested.parameter X is equal to $ NUTS_ENGINE_NESTED_PARAMETER=X nuts

While most options are a single value, some are represented as a list (indicated with the square brackets in the table below). To provide multiple values through flags or environment variables you can separate them with a comma (var1,var2). If you need to provide an actual value with a comma, you can escape it with a backslash (\,) to avoid it having split into multiple values.

Ordering

Command line parameters have the highest priority, then environment variables, then parameters from the configfile and lastly defaults. The location of the configfile is determined by the environment variable NUTS_CONFIGFILE or the commandline parameter --configfile. If both are missing the default location ./nuts.yaml is used. :

CLI > ENV > Config File > Defaults

Server options

The following options can be configured on the server:

Server Options
Key Default Description

configfile cpuprofile

./config/nuts.yaml

Nuts config file When set, a CPU profile is written to the given path. Ignored when strictmode is set.

datadir ./data Directory where the node stores its files.
internalratelimiter true When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode.
loggerformat text Log format (text, json)

strictmode url

true

When set, insecure settings are forbidden. Public facing URL of the server (required). Must be HTTPS when strictmode is set.

verbosity info Log level (trace, debug, info, warn, error)

httpclient.timeout Crypto crypto.storage crypto.external.address

30s

Request time-out for HTTP clients, such as '10s'. Refer to Golang's 'time.Duration' syntax for a more elaborate description of the syntax.

Storage to use, 'external' for an external backend (experimental), 'fs' for file system (for development purposes), 'vaultkv' for Vault KV store (recommended, will be replaced by external backend in future). Address of the external storage service.

crypto.external.timeout crypto.vault.address

100ms

Time-out when invoking the external storage backend, in Golang time.Duration string format (e.g. 1s). The Vault address. If set it overwrites the VAULT_ADDR env var.

crypto.vault.pathprefix kv The Vault path prefix.

crypto.vault.timeout crypto.vault.token Discovery

5s

Timeout of client calls to Vault, in Golang time.Duration string format (e.g. 1s). The Vault token. If set it overwrites the VAULT_TOKEN env var.

discovery.client.refresh_interval 10m0s Interval at which the client synchronizes with the Discovery Server; refreshing Verifiable Presentations of local DIDs and loading changes, updating the local copy. It only will actually refresh registrations of local DIDs that about to expire (less than 1/4th of their lifetime left). Specified as Golang duration (e.g. 1m, 1h30m).
discovery.definitions.directory ./config/discovery Directory to load Discovery Service Definitions from. If not set, the discovery service will be disabled. If the directory contains JSON files that can't be parsed as service definition, the node will fail to start.

discovery.server.ids HTTP

[]

IDs of the Discovery Service for which to act as server. If an ID does not map to a loaded service definition, the node will fail to start.

http.log metadata What to log about HTTP requests. Options are 'nothing', 'metadata' (log request method, URI, IP and response code), and 'metadata-and-body' (log the request and response body, in addition to the metadata).

http.internal.address http.internal.auth.audience http.internal.auth.authorizedkeyspath http.internal.auth.type

127.0.0.1:8081

Address and port the server will be listening to for internal-facing endpoints. Expected audience for JWT tokens (default: hostname) Path to an authorized_keys file for trusted JWT signers Whether to enable authentication for /internal endpoints, specify 'token_v2' for bearer token mode or 'token' for legacy bearer token mode.

http.public.address JSONLD

:8080

Address and port the server will be listening to for public-facing endpoints.

jsonld.contexts.localmapping [https://nuts.nl/credentials/v1=assets/contexts/nuts.ldjson,https://www.w3.org/2018/credentials/v1=assets/contexts/w3c-credentials-v1.ldjson,https://w3id.org/vc/status-list/2021/v1=assets/contexts/w3c-statuslist2021.ldjson,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json=assets/contexts/lds-jws2020-v1.ldjson,https://schema.org=assets/contexts/schema-org-v13.ldjson] This setting allows mapping external URLs to local files for e.g. preventing external dependencies. These mappings have precedence over those in remoteallowlist.

jsonld.contexts.remoteallowlist PKI

[https://schema.org,https://www.w3.org/2018/credentials/v1,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json,https://w3id.org/vc/status-list/2021/v1]

In strict mode, fetching external JSON-LD contexts is not allowed except for context-URLs listed here.

pki.maxupdatefailhours 4 Maximum number of hours that a denylist update can fail

pki.softfail Storage storage.sql.connection policy policy.address

true

Do not reject certificates if their revocation status cannot be established when softfail is true

Connection string for the SQL database. If not set it, defaults to a SQLite database stored inside the configured data directory. Note: using SQLite is not recommended in production environments. If using SQLite anyways, remember to enable foreign keys ('_foreign_keys=on') and the write-ahead-log ('_journal_mode=WAL').

The address of a remote policy server. Mutual exclusive with policy.directory.

policy.directory ./config/policy Directory to read policy files from. Policy files are JSON files that contain a scope to PresentationDefinition mapping. Mutual exclusive with policy.address.

Options specific for did:nuts/gRPC

The following table contains additional (deprecated) options that are relevant for use cases that use did:nuts DIDs and/or the gRPC network. If your use case does not use these features, you can ignore this table.

did:nuts/gRPC Server Options
Key Default Description

tls.certfile tls.certheader tls.certkeyfile tls.offload

PEM file containing the certificate for the gRPC server (also used as client certificate). Required in strict mode. Name of the HTTP header that will contain the client certificate when TLS is offloaded for gRPC. PEM file containing the private key of the gRPC server certificate. Required in strict mode. Whether to enable TLS offloading for incoming gRPC connections. Enable by setting it to 'incoming'. If enabled 'tls.certheader' must be configured as well.

tls.truststorefile Auth

./config/ssl/truststore.pem

PEM file containing the trusted CA certificates for authenticating remote gRPC servers. Required in strict mode.

auth.accesstokenlifespan 60 defines how long (in seconds) an access token is valid. Uses default in strict mode.
auth.clockskew 5000 allowed JWT Clock skew in milliseconds
auth.contractvalidators [irma,dummy,employeeid] sets the different contract validators to use
auth.irma.autoupdateschemas true set if you want automatically update the IRMA schemas every 60 minutes.

auth.irma.schememanager Events

pbdf

IRMA schemeManager to use for attributes. Can be either 'pbdf' or 'irma-demo'.

events.nats.hostname 0.0.0.0 Hostname for the NATS server

events.nats.port events.nats.storagedir

4222

Port where the NATS server listens on Directory where file-backed streams are stored in the NATS server

events.nats.timeout GoldenHammer

30

Timeout for NATS server operations

goldenhammer.enabled true Whether to enable automatically fixing DID documents with the required endpoints.

goldenhammer.interval Network

10m0s

The interval in which to check for DID documents to fix.

network.bootstrapnodes [] List of bootstrap nodes ('<host>:<port>') which the node initially connect to.
network.connectiontimeout 5000 Timeout before an outbound connection attempt times out (in milliseconds).
network.enablediscovery true Whether to enable automatic connecting to other nodes.
network.grpcaddr :5555

Local address for gRPC to listen on. If empty the gRPC server won't be started and other nodes will not be able to connect to this node (outbound connections can still be made).

network.maxbackoff network.nodedid

24h0m0s

Maximum between outbound connections attempts to unresponsive nodes (in Golang duration format, e.g. '1h', '30m'). Specifies the DID of the party that operates this node. It is used to identify the node on the network. If the DID document does not exist of is deactivated, the node will not start.

network.protocols [] Specifies the list of network protocols to enable on the server. They are specified by version (1, 2). If not set, all protocols are enabled.
network.v2.diagnosticsinterval 5000 Interval (in milliseconds) that specifies how often the node should broadcast its diagnostic information to other nodes (specify 0 to disable).

network.v2.gossipinterval Storage storage.bbolt.backup.directory

5000

Interval (in milliseconds) that specifies how often the node should gossip its new hashes to other nodes.

Target directory for BBolt database backups.

storage.bbolt.backup.interval storage.redis.address storage.redis.database storage.redis.password storage.redis.username storage.redis.sentinel.master

0s

Interval, formatted as Golang duration (e.g. 10m, 1h) at which BBolt database backups will be performed. Redis database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. Redis database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. Redis database password. If set, it overrides the username in the connection URL. Redis database username. If set, it overrides the username in the connection URL. Name of the Redis Sentinel master. Setting this property enables Redis Sentinel.

storage.redis.sentinel.nodes storage.redis.sentinel.password storage.redis.sentinel.username storage.redis.tls.truststorefile storage.session.redis.address storage.session.redis.database storage.session.redis.password storage.session.redis.username storage.session.redis.sentinel.master

[]

Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel. Password for authenticating to Redis Sentinels. Username for authenticating to Redis Sentinels. PEM file containing the trusted CA certificate(s) for authenticating remote Redis servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address). Redis database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. Redis database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. Redis database password. If set, it overrides the username in the connection URL. Redis database username. If set, it overrides the username in the connection URL. Name of the Redis Sentinel master. Setting this property enables Redis Sentinel.

storage.session.redis.sentinel.nodes

[]

Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel.
storage.session.redis.sentinel.passwor d Password for authenticating to Redis Sentinels.
storage.session.redis.sentinel.usernam e Username for authenticating to Redis Sentinels.

storage.session.redis.tls.truststorefi VCR vcr.openid4vci.definitionsdir

le

PEM file containing the trusted CA certificate(s) for authenticating remote Redis servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address).

Directory with the additional credential definitions the node could issue (experimental, may change without notice).

vcr.openid4vci.enabled true Enable issuing and receiving credentials over OpenID4VCI.
vcr.openid4vci.timeout 30s Time-out for OpenID4VCI HTTP client operations.

This table is automatically generated using the configuration flags in the core and engines. When they're changed the options table must be regenerated using the Makefile:

$ make docs

Secrets

All options ending with token or password are considered secrets and can only be set through environment variables or the config file.

Strict mode

Several of the server options above allow the node to be configured in a way that is unsafe for production environments, but are convenient for testing or development. The node can be configured to run in strict mode (default) to prevent any insecure configurations. Below is a summary of the impact strictmode=true has on the node and its configuration.

Save storage of any private key material requires some serious consideration. For this reason the crypto.storage backend must explicitly be set.

Private transactions can only be exchanged over authenticated nodes. Therefore is requires TLS to be configured through tls.{certfile,certkeyfile,truststore}. To verify that authentication is correctly configured on your node, check the network.auth_config status on the /health endpoint. See Monitoring <nuts-node-monitoring> for more details.

The incorporated IRMA server is automatically changed to production mode. In fact, running in strict mode is the only way to enable IRMA's production mode. In addition, it requires auth.irma.schememanager=pbdf.

As a general safety precaution auth.contractvalidators ignores the dummy option if configured, requesting an access token from another node on /n2n/auth/v1/accesstoken does not return any error details, auth.accesstokenlifespan is always 60 seconds, http.default.cors.origin does not allow a wildcard (*), json-ld context can only be downloaded from trusted domains configured in jsonld.contexts.remoteallowlist, and the internalratelimiter is always on.

Interacting with remote Nuts nodes requires HTTPS: it will refuse to connect to plain HTTP endpoints when in strict mode.

nuts-node's People

Contributors

aikedejongste avatar beardedfoo avatar dependabot[bot] avatar gerardsn avatar henk-hofs-pink avatar jelmerterwal avatar jeroendee avatar joostfaassen avatar jorisheadease avatar mbotman avatar pascaldekloe avatar reinkrul avatar rolandgroen avatar stevenvegt avatar woutslakhorst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nuts-node's Issues

Add generic VerifiableCredential support

This is a tracking issue

  • implement concept mapping structure #69
  • add NutsOrganizationCredential #100
  • update documentation
  • search API #131
  • implement issuing #100
  • implement revocation #130
  • implement resolving #125
  • connect to network #127
  • keep in line with RFC011 and RFC012
  • embed templates using go1.16 #100
  • add config params for trusted issuers #149
  • CLI #173

Echo server is not exposed to the outside world by default

Since it binds on localhost:1323 you'd have to configure it to have any endpoints being available from the outside at all, which is not very convenient.

http:
  default:
    address: :1323

Maybe better: bind on :1323 (all interfaces) by default so it's available from the outside (Docker container e.g.), and add some extra checks to strict mode, disallowing unsafe configuration. Maybe disallow this 'bind to all interfaces' in strict mode to enforce administrators to provide alternative bindings?

Auth: Dutch dates in English contract texts

EN:PractitionerLogin:v3 I hereby declare to act on behalf of Company #686. This declaration is valid from maandag, 22 februari 2021 16:07:17 until maandag, 22 februari 2021 17:07:17.

See unit test: auth/services/contract/notary_test.go

server flag --network.bootstrapNodes adds nodes 3 times

nuts server --network.bootstrapNodes node1:5555 results in
network.bootstrapNodes -> [node1:5555 node1:5555 node1:5555]

nuts server --network.bootstrapNodes node1:5555,node2:555 results in
network.bootstrapNodes -> [node1:5555 node2:5555 node1:5555 node2:5555 node1:5555 node2:5555]

Implement VDR using network

currently it calls the store directly. It must do everything via the network and use the callbacks to store data in the store.

Improve network pub-sub

Applications (like the registry) can subscribe to specific document types on the network. Then the network engine will call the receiver func. when a document is received. The current implementation is very naive however;

  • It's not persistent, meaning if the server crashes halfway some documents may not be received by the subscriber
  • It's not ordered, so subscribers will receive documents out-of-order at some point
  • It's not retryable, so error'd documents will never be retried by the application.

This needs a better solution.

Log version at startup and include it in diagnostics page

Now there's no way to determine what version a running node has. It would be convenient if it was displayed on the status page and logged on node startup;

  • Git branch that the build was made from
  • Git commit ID
  • Build time(?)
  • Git tag (for identifying releases?)

Fix check on kid in jwk field

Node could not parse network documents:

nuts  | time="2021-02-18T12:25:05Z" level=error msg="Error while checking peer document on local node (peer=71d2a790-6bef-4db7-8a6f-bb81e57fc11d, document=cc137e657740fd2bddb042258268877d8c6ca26b1d21f75fd8f1a8c313932ba9): received document is invalid (peer=71d2a790-6bef-4db7-8a6f-bb81e57fc11d,pref=cc137e657740fd2bddb042258268877d8c6ca26b1d21f75fd8f1a8c313932ba9): document validation failed: when present, the `jwk` must contain a valid `kid`" module=Network

This check is not according to RFC004. The check for a kid on an embedded key is wrong.

Add DID Doc Update validation

Update checks are not complete.

  • Version of a new doc does not start with 0
  • Version or updatedAt timestamp of a updated doc !> previous
  • New keys added should be added to the keystore
  • Removed keys should be removed from the keystore
  • Resolving a chain of controllers (more than 1)
  • Deactivation of ducuments
  • Timeline validation according to RFC004 3.4.1
  • Full e2e test which will test the complete life cycle of a document:
    • Creation of a new document A
    • Update Document A with a new service
    • Update Document A with a new authentication key, old one should be removed
    • Creation of New Document B
    • Update of Document B controller which transfers control to Document A
    • Update of Document B with new service endpoints, signed by Document A
    • Creation of Document C
    • Update of Document C which makes Document B the controller
    • Deactivation of Document C
    • Deactivation of Document A and thus also Document B

Migrate nuts-auth

And implement DIDs according the new updated RFC003 at the same time.

Decide which endpoints need CORS enabled

Currently CORS is enabled for all endpoints (because appearantly nuts-auth needs it?), but this could lead to security vulnerabilities. We need to decide which endpoints really need it and just enable it on those. Maybe using the new HTTPConfig configuration options.

Separate CLI config from server config

We now have 1 type of config (core/engine) which is loaded for both CLI and server, which creates ambiguity. This should be separated; the CLI should have specific flags (e.g. remote server address, time-outs) which are specific for the invocation of CLI and the server config shouldn't include these CLI-specific flags.

Refactor Engine struct to interface

The Engine struct could be refactored to an interface which can be composed of the existing Runnable, Configurable and Diagnosable interfaces.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.