Skip to content

Commit

Permalink
Merge pull request #4 from pulledtim/token-api
Browse files Browse the repository at this point in the history
extend ishare support
  • Loading branch information
pulledtim authored May 15, 2023
2 parents 9113735 + 35861f1 commit ca76938
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 74 deletions.
48 changes: 48 additions & 0 deletions api/satellite.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ paths:
get:
tags:
- Satellite
parameters:
- $ref: '#/components/parameters/Eori'
- $ref: '#/components/parameters/CertificateSubjectName'
operationId: getParties
responses:
'200':
Expand All @@ -52,7 +55,42 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/PartiesResponse'
/party/{partyId}:
get:
tags:
- Satellite
parameters:
- $ref: '#/components/parameters/PartyId'
operationId: getPartyById
responses:
'200':
description: Get the party with the requested id.
content:
application/json:
schema:
$ref: '#/components/schemas/PartyResponse'
'404':
description: No such party was found.
components:
parameters:
PartyId:
name: partyId
in: path
required: true
schema:
type: string
Eori:
name: eori
in: query
required: false
schema:
type: string
CertificateSubjectName:
name: certificate_subject_name
in: query
required: false
schema:
type: string
schemas:
TokenBody:
type: object
Expand Down Expand Up @@ -99,6 +137,11 @@ components:
properties:
parties_token:
type: string
PartyResponse:
type: object
properties:
party_token:
type: string
PartiesInfo:
type: object
properties:
Expand All @@ -108,6 +151,11 @@ components:
type: array
items:
$ref: '#/components/schemas/Party'
PartyInfo:
type: object
properties:
party_info:
$ref: '#/components/schemas/Party'
Party:
type: object
properties:
Expand Down
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<!-- docker -->
<exec.mainClass>org.fiware.gaiax.wrapper.Application</exec.mainClass>
<image.registry>quay.io</image.registry>
<image.repository>pulledtim</image.repository>
<image.repository>wi_stefan</image.repository>

<!-- lazy dev -->
<version.org.mapstruct>1.5.3.Final</version.org.mapstruct>
Expand Down Expand Up @@ -90,9 +90,9 @@
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.fiware.tmforum</groupId>
<artifactId>mapping</artifactId>
<version>0.1</version>
<groupId>io.github.wistefan</groupId>
<artifactId>ngsi-ld-java-mapping</artifactId>
<version>0.1.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
Expand Down Expand Up @@ -495,7 +495,7 @@
<image>registry.access.redhat.com/ubi8/openjdk-17:1.13</image>
</from>
<to>
<image>${image.registry}/${image.repository}/trusted-issuers-registry-wrapper</image>
<image>${image.registry}/${image.repository}/${project.artifactId}</image>
<tags>
<tag>${project.version}</tag>
</tags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.micronaut.security.token.jwt.validator.JwtTokenValidator;
import io.micronaut.security.token.jwt.validator.JwtValidator;
import jakarta.inject.Singleton;
import org.fiware.gaiax.tir.repository.PartiesRepo;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;

Expand All @@ -21,22 +22,25 @@
public class IShareJwtValidator extends JwtTokenValidator {

private final JWTService jwtService;
private final PartiesRepo partiesRepo;

public IShareJwtValidator(
Collection<SignatureConfiguration> signatureConfigurations,
Collection<EncryptionConfiguration> encryptionConfigurations,
Collection<GenericJwtClaimsValidator> genericJwtClaimsValidators,
JwtAuthenticationFactory jwtAuthenticationFactory,
JWTService jwtService) {
JWTService jwtService, PartiesRepo partiesRepo) {
super(signatureConfigurations, encryptionConfigurations, genericJwtClaimsValidators, jwtAuthenticationFactory);
this.jwtService = jwtService;
this.partiesRepo = partiesRepo;
}

public IShareJwtValidator(JwtValidator validator,
JwtAuthenticationFactory jwtAuthenticationFactory,
JWTService jwtService) {
JWTService jwtService, PartiesRepo partiesRepo) {
super(validator, jwtAuthenticationFactory);
this.jwtService = jwtService;
this.partiesRepo = partiesRepo;
}

@Override
Expand Down
32 changes: 23 additions & 9 deletions src/main/java/org/fiware/gaiax/tir/auth/JWTService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.nimbusds.jose.util.X509CertUtils;
import io.micronaut.context.annotation.Replaces;
import jakarta.inject.Singleton;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.fiware.gaiax.satellite.model.TrustedCAVO;
import org.fiware.gaiax.tir.configuration.Party;
import org.fiware.gaiax.tir.configuration.SatelliteProperties;
import org.fiware.gaiax.tir.configuration.TrustedCA;
import org.fiware.gaiax.tir.repository.PartiesRepo;

import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
Expand All @@ -24,12 +25,14 @@
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
import java.util.List;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor
@Singleton
public class JWTService {

private final PartiesRepo partiesRepo;
private final SatelliteProperties satelliteProperties;

public DecodedJWT validateJWT(String jwtString) {
Expand All @@ -46,12 +49,21 @@ public DecodedJWT validateJWT(String jwtString) {
} catch (JWTVerificationException jwtVerificationException) {
throw new IllegalArgumentException("Token not verified.", jwtVerificationException);
}
satelliteProperties.getTrustedList().stream()
Optional<String> optionalTrustedCA = satelliteProperties.getTrustedList().stream()
.map(TrustedCA::crt)
.map(this::getPem)
.filter(pem -> pem.equals(caCert))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("The ca is not trusted."));
.filter(caCert::equals)
.findFirst();
if (optionalTrustedCA.isEmpty()) {
partiesRepo.getPartyById(decodedJWT.getClaim("iss").asString())
.map(Party::crt)
.map(JWTService::getPemChain)
// get the client cert
.map(parsedCerts -> parsedCerts.get(0))
.filter(clientCert::equals)
.orElseThrow(() -> new IllegalArgumentException("No trusted CA and no trusted party found."));
}

return decodedJWT;
}

Expand All @@ -74,23 +86,25 @@ private String getPem(String cert) {
.replaceAll("\\s", "");
}

public List<X509Certificate> getCertificates(String crt) {
public static List<X509Certificate> getCertificates(String crt) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
crt.getBytes());
CertificateFactory certificateFactory = null;
try {
certificateFactory = CertificateFactory.getInstance("X.509");
return (List<X509Certificate>) certificateFactory.generateCertificates(
return (List<X509Certificate>) certificateFactory.generateCertificates(
byteArrayInputStream);
} catch (CertificateException e) {
throw new IllegalArgumentException(e);
}
}

public static String getThumbprint(X509Certificate cert) throws CertificateEncodingException {
MessageDigest sha256 = DigestUtils.getSha256Digest();
return DatatypeConverter.printHexBinary(sha256.digest(cert.getEncoded()));
}
public List<String> getPemChain(String crt) {

public static List<String> getPemChain(String crt) {

return getCertificates(crt).stream().map(cert -> {
try {
Expand Down
14 changes: 9 additions & 5 deletions src/main/java/org/fiware/gaiax/tir/issuers/TrustedIssuer.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package org.fiware.gaiax.tir.issuers;

import lombok.*;
import io.github.wistefan.mapping.annotations.AttributeGetter;
import io.github.wistefan.mapping.annotations.AttributeSetter;
import io.github.wistefan.mapping.annotations.AttributeType;
import io.github.wistefan.mapping.annotations.MappingEnabled;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.fiware.tmforum.common.domain.EntityWithId;
import org.fiware.tmforum.mapping.annotations.AttributeGetter;
import org.fiware.tmforum.mapping.annotations.AttributeSetter;
import org.fiware.tmforum.mapping.annotations.AttributeType;
import org.fiware.tmforum.mapping.annotations.MappingEnabled;

/**
* Example data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package org.fiware.gaiax.tir.repository;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.fiware.tmforum.mapping.annotations.Ignore;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,18 @@
import io.micronaut.scheduling.annotation.Scheduled;
import jakarta.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.fiware.gaiax.satellite.model.TrustedCAVO;
import org.fiware.gaiax.tir.auth.JWTService;
import org.fiware.gaiax.tir.configuration.Party;
import org.fiware.gaiax.tir.configuration.SatelliteProperties;
import org.fiware.gaiax.tir.configuration.TrustedCA;
import org.fiware.gaiax.tir.issuers.IssuersProvider;

import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Slf4j
Expand All @@ -33,39 +27,14 @@ public class InMemoryPartiesRepo implements PartiesRepo {
private final SatelliteProperties satelliteProperties;
private final IssuersProvider issuersProvider;
private final List<Party> parties;
private final List<TrustedCAVO> trustedCAS;
private final HttpClient httpClient;
private final JWTService jwtService;

public InMemoryPartiesRepo(SatelliteProperties satelliteProperties, IssuersProvider issuersProvider,
HttpClient httpClient, JWTService jwtService) {
HttpClient httpClient) {
this.parties = satelliteProperties.getParties();
this.satelliteProperties = satelliteProperties;
this.issuersProvider = issuersProvider;
this.httpClient = httpClient;
this.jwtService = jwtService;
this.trustedCAS = new ArrayList<>();
}

private void updateTrustedCAs(List<Party> parties) {

Map<String, TrustedCAVO> tcaMap = new HashMap<>();
parties.stream().forEach(p -> {
List<X509Certificate> certs = jwtService.getCertificates(p.crt());
if (certs.size() != 3) {
// we ignore everything that is not an x5c chain.
return;
}
// it must be the third one.
toTrustedCaVO(certs.get(2)).ifPresent(tCA -> tcaMap.put(tCA.getCertificateFingerprint(), tCA));
});
satelliteProperties.getTrustedList().stream()
.forEach(trustedCA -> {
toTrustedCaVO(jwtService.getCertificates(trustedCA.crt()).get(0)).ifPresent(
tCA -> tcaMap.put(tCA.getCertificateFingerprint(), tCA));
});
trustedCAS.clear();
trustedCAS.addAll(tcaMap.values());
}

private Optional<TrustedCAVO> toTrustedCaVO(X509Certificate caCert) {
Expand All @@ -91,8 +60,6 @@ private String isValid(X509Certificate cert) {
}
}



@Scheduled(fixedDelay = "15s")
public void updateParties() {
List<Party> updatedParties = new ArrayList<>();
Expand All @@ -115,12 +82,11 @@ public void updateParties() {
new Party(didDocument.getId(), didDocument.getId(), didDocument.getId(), "active", cert));
}
} catch (IllegalArgumentException e) {
log.warn("Cannot resolve issuer, skip.");
log.warn("Cannot resolve issuer {}, skip.", ti.getIssuer());
}
});
parties.clear();
parties.addAll(updatedParties);
updateTrustedCAs(parties);
}

// port not supported yet
Expand Down Expand Up @@ -148,7 +114,15 @@ private String getDIDDocumentPath(String did) {
}

@Override public List<TrustedCAVO> getTrustedCAs() {
return trustedCAS;
List<TrustedCAVO> trustedCAVOS = new ArrayList<>();

satelliteProperties.getTrustedList().stream()
.forEach(trustedCA -> {
toTrustedCaVO(JWTService.getCertificates(trustedCA.crt()).get(0)).ifPresent(
tCA -> trustedCAVOS.add(tCA));
});

return trustedCAVOS;
}

@Override public Optional<Party> getPartyById(String id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface PartiesRepo {
List<Party> getParties();

List<TrustedCAVO> getTrustedCAs();

Optional<Party> getPartyById(String id);

Optional<Party> getPartyByDID(String did);
Expand Down
Loading

0 comments on commit ca76938

Please sign in to comment.