Skip to content
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

docs: add decision record about customizable JWSSigners #4396

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Allowing custom `JWSSigner` implementations

## Decision

To allow custom `JWSSigner` implementations, the `TokenGenerationService` needs to be refactored, in particular the way
how `PrivateKey` objects are handled.

## Rationale

In the current EDC implementation, the private key is always resolved from the vault, and a `JWSSigner` implementation
is instantiated based on the algorithm of the key.

Some High-Security Modules (HSMs) have a feature where the signing of content can be done with a remote call while
the private key material does not leave the HSM itself.

To support this feature in EDC, the `TokenGenerationService` and its implementation, the `JwtGenerationService` must be
refactored to accommodate the custom `JWSSigner`.

## Approach

- refactor the `generate()` method: instead of taking a `Supplier<PrivateKey`, the `TokenGenerationService` will take a
plain String containing the private key ID.
- a new interface `JwsSignerProvider` is added in its own SPI module `jwt-signer-spi`:
```java
public interface JwsSignerProvider extends Function<String, JWSSigner> {
// marker interface
}
```
Note that this will expose Nimbus classes in the SPI module!
- the `JwtGenerationService` takes in its constructor a `JwsSignerProvider`, which is then used upon token generation to
get a `JWSSigner` for a particular private key ID.
```java
@Override
public Result<TokenRepresentation> generate(String privateKeyId, @NotNull TokenDecorator... decorators) {
var tokenSigner = jwsGeneratorFunction.apply(privateKeyId);
if (tokenSigner == null) {
return Result.failure("JWSSigner cannot be generated for private key '%s'".formatted(privateKeyId));
}
//...
}
```
- The default implementation will simply resolve the private key from
the vault and create a `JWSSigner` for it:
```java
@Provider(isDefault = true)
public JwsSignerProvider defaultSignerProvider() {
return privateKeyId -> {
var pk = privateKeyResolver.resolvePrivateKey(privateKeyId).orElseThrow(/*exception*/);
return CryptoConverter.createSignerFor(pk);
};
}
```
1 change: 1 addition & 0 deletions docs/developer/decision-records/README.md
Original file line number Diff line number Diff line change
@@ -58,3 +58,4 @@
- [2024-05-24 Dataplane Selection Improvements](./2024-05-24-dataplane-selection-improvements/)
- [2024-06-24 Api Authentication Configuration](./2024-06-24-api-authentication-configuration/)
- [2024-07-03 Additional CatalogRequest scope parameter](./2024-07-03-additional-catalogrequest-param/)
- [2024-08-05 Custom JWSSigner Implementations](./2024-08-05-custom-jwssigners/)

Unchanged files with check annotations Beta

maven/mavencentral/com.apicatalog/carbon-did/0.3.0, Apache-2.0, approved, clearlydefined

Check warning on line 1 in DEPENDENCIES

GitHub Actions / check / Dash-Verify-Licenses

Restricted Dependencies found

Some dependencies are marked 'restricted' - please review them
maven/mavencentral/com.apicatalog/copper-multibase/0.5.0, Apache-2.0, approved, #14501
maven/mavencentral/com.apicatalog/copper-multicodec/0.1.1, Apache-2.0, approved, #14500
maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.14.0, Apache-2.0, approved, #14503