🔗 技術調査 - EclipseEDC
目次

🔗 技術調査 - EclipseEDC

概要

「組織間でデータを安全に共有したいが、相手にデータの主権を渡したくない」。この課題に対して、欧州を中心にデータスペースという概念が広がっています。Eclipse EDC はその参照実装として注目されているフレームワークです。本記事では、Eclipse EDC のアーキテクチャからデータモデル、構築・運用方法まで包括的に調査した結果をまとめます。

Eclipse EDC とは

Eclipse EDC(Eclipse Dataspace Components)は、組織間で主権的かつ安全にデータを共有するためのオープンソースフレームワークです。Apache 2.0 ライセンスで提供されており、商用利用を前提に設計されています。

Eclipse Foundation の技術プロジェクト(technology.edc)として管理されています。Eclipse Dataspace Working Group(EDWG)のガバナンス下で開発が進められています。

データスペースとは

データスペースは、複数組織間の合意と技術インフラが一体となった仕組みです。信頼関係がない企業間でも、データ主権を保ちながらデータを交換できます。

データスペース = 多組織間合意 + 技術インフラ(フェデレーテッドネットワーク)

EDC はこのデータスペースを構築・運用するための参照実装です。

IDSA・Gaia-X との関係

要素 説明
IDSA 主権的データ交換と DSP 標準を策定する国際データスペース協会
DSP IDSA が定義するデータスペース間通信プロトコル。ISO/IEC 標準化を申請中
Gaia-X 分散型デジタル信頼フレームワーク。EDC は Gaia-X トラストアンカーと統合
Eclipse EDC IDSA DSP を実装し、Gaia-X トラストフレームワークと互換性を持つ参照実装

Eclipse Foundation における位置づけ

項目 内容
プロジェクト ID technology.edc
ガバナンス Eclipse Dataspace Working Group - EDWG
EDWG 設立 2023年12月
ライセンス Apache 2.0

主要な支援企業・組織

組織 種別 関与
Microsoft 企業 - EDWG 創立メンバー 開発・プロトコル策定
Fraunhofer 研究機関 - EDWG 創立メンバー 開発・技術設計 - ISST
IDSA 標準化団体 - EDWG 創立メンバー プロトコル仕様
T-Systems 企業 - EDWG 創立メンバー 実装・運用
Amadeus 企業 - EDWG 創立メンバー 実装
iSHARE Foundation 非営利 - EDWG 創立メンバー データ主権推進
SAP 企業 EDC プロジェクト支援
Catena-X / Cofinity-X コンソーシアム 自動車産業向け実装

特徴

特徴 内容
データ主権の実現 データ所有者がアクセス条件・利用目的・共有先を完全に制御
契約ベースの交換 データ転送前に機械可読な契約合意が必須
ポリシーエンジン ODRL 標準に基づく宣言的ポリシーの自動執行
デュアルプレーン構造 制御プレーンとデータプレーンの責務分離
モジュラーアーキテクチャ SPI・コア・拡張・データプロトコルの4層構成
マルチクラウド対応 HTTP、S3、Kafka など複数プロトコルとクラウドバックエンドに対応
標準プロトコル準拠 DSP 0.8 / 2024/1 / 2025/1 の複数バージョンをサポート
分散型 ID 管理 OAuth2・分散型 ID・証明書による信頼検証
オープンソース Apache 2.0 ライセンスで商用利用可能

データ主権の実現方法

要素 説明
制御プレーン 契約交渉とポリシー執行を担当するオーケストレーション層
データプレーン 実際のデータ転送を実行する処理層
契約交渉 データ転送前に両者が合意する機械可読な利用条件
ポリシー執行 ODRL ベースのルールの自動評価・適用

モジュラーアーキテクチャ

モジュール種別 役割
SPI サービスプロバイダーインターフェース。拡張ポイントの定義
Core フレームワークの基本実装 - TransferProcessManager 等
Extension 技術・クラウド固有の機能を追加するプラグイン
Data Protocols DSP・HTTP 等の通信プロトコル実装

@Extension アノテーションと依存性注入(@Provider / @Inject)により、カスタム拡張を差し込めます。

マルチクラウド対応

対応カテゴリ 具体例
ストレージバックエンド PostgreSQL、Azure CosmosDB、H2
シークレット管理 Azure Key Vault 等のクラウドプロバイダー対応
データ転送プロトコル HTTP/S、S3、Kafka
データプレーン選択 DataPlaneSelector によるリモート・組み込み切り替え

標準プロトコル準拠

プロトコル バージョン 位置づけ
DSP 0.8 レガシー 既存実装との後方互換
DSP 2024/1 現安定版 本番環境推奨
DSP 2025/1 次世代 ISO/IEC 標準化申請中
ODRL - ポリシー記述標準
DCAT 3 - データカタログ記述標準

オープンソースエコシステム

プロジェクト 分野 概要
Catena-X / Tractus-X 自動車 OEM・サプライヤー間データ共有
EONA-X モビリティ・観光 欧州交通データスペース
Cofinity-X 自動車 Catena-X 商用実装

構造

システムコンテキスト図

データ公開・転送 カタログ参照・データ取得 設定・管理 認証・トークン検証 トークン発行 カタログ情報登録・連携 カタログ提供 データ読み取り・書き込み Data Provider Data Consumer Operator EDC Connector Identity Provider Catalog Service Data Backend
要素名 説明
Data Provider データを提供する組織またはシステム。データ資産の公開と転送の許可
Data Consumer データを要求する組織またはシステム。カタログの参照と契約交渉を経たデータ取得
Operator コネクターの運用・管理担当者。Management API を通じた設定・監視
EDC Connector データスペースにおける安全なデータ交換を実現するコネクター。本調査対象
Identity Provider 参加者の認証・認可を担うシステム。DAPS または DID/DCP によるトークンの発行・検証
Catalog Service データ資産のカタログ情報を集約・提供するシステム。Federated Catalog として機能
Data Backend 実データを格納するストレージ。HTTP エンドポイント、Kafka トピック、クラウドストレージ等

コンテナ図

EDC Connector REST DSP プロトコル DSP プロトコル データ取得 トークン検証 データ読み書き Operator Data Provider Data Consumer Identity Provider Data Backend Management API DSP API Public API Observability API Control Plane Data Plane Data Plane Selector
要素名 説明
Management API Operator 向けの管理インターフェース。資産・ポリシー・契約・転送プロセスの CRUD 操作の提供
DSP API 他コネクターとの通信インターフェース。DSP v0.8 / v2024 / v2025 に対応し、カタログ・契約交渉・転送プロセスメッセージの処理
Public API Data Consumer がデータを直接取得するためのエンドポイント。Data Plane が提供
Observability API ヘルスチェック・死活監視用エンドポイント。readiness / liveness / startup プローブの提供
Control Plane 契約交渉・ポリシー執行・カタログ管理・転送調整を担うオーケストレーション層
Data Plane 実データの転送処理を担う層。パイプライン方式で HTTP / Kafka 等のバックエンドと接続
Data Plane Selector Control Plane からの転送要求を適切な Data Plane インスタンスにルーティング

コンポーネント図

Control Plane

Control Plane 検証 Management API DSP API Identity Provider Data Plane Selector Asset Service Catalog Service Contract Negotiation Service Transfer Process Service Policy Engine Protocol Token Validator Dataspace Profile Context Registry Asset Index Contract Negotiation Store Transfer Process Store Event Router
要素名 説明
Asset Service データ資産のライフサイクル管理。資産の登録・更新・削除・検索
Catalog Service カタログの公開と参照の管理。DSP API 経由のカタログリクエストの処理
Contract Negotiation Service 契約交渉のライフサイクル管理。オファー・アグリーメントの状態遷移制御
Transfer Process Service データ転送プロセスのライフサイクル管理。転送の開始・監視・完了の調整
Policy Engine ODRL に基づくポリシーの評価・執行。アクセスポリシーと利用ポリシーの両方を処理
Protocol Token Validator DSP プロトコルレベルの認証トークン検証。Identity Provider と連携して信頼を確立
Dataspace Profile Context Registry 複数の DSP バージョンをルーティングするレジストリ。プロトコルごとの認証・語彙・エンドポイント管理
Asset Index 資産メタデータの永続化ストア。SQL 実装とインメモリ実装を提供
Contract Negotiation Store 契約交渉エンティティの永続化ストア。状態マシンと統合した一貫性保証
Transfer Process Store 転送プロセスエンティティの永続化ストア。状態マシンと統合した一貫性保証
Event Router 資産・契約・転送の状態変化イベントを外部サブスクライバーに配信

Data Plane

Data Plane EDR - 転送パラメーター 読み取り 書き込み 読み取り 書き込み Public API Data Plane Selector Data Backend Control Plane Data Flow Controller Pipeline Service Transfer Service Data Plane Store HTTP Data Source HTTP Data Sink Kafka Data Source Kafka Data Sink Data Address Validator EDR Manager
要素名 説明
Data Flow Controller Control Plane からの転送指示を受け取り、Data Plane 内の処理フローを制御
Pipeline Service データ転送パイプラインのオーケストレーション。ソースとシンクを組み合わせた転送の実行
Transfer Service 各転送プロトコルの実装コントラクト。プラグイン可能なトランスポートメカニズムを定義する SPI
Data Plane Store 転送プロセスの状態を永続化するストア。状態マシンによるリトライと状態遷移の管理
HTTP Data Source HTTP / HTTPS エンドポイントからデータを読み取るソース実装
HTTP Data Sink HTTP / HTTPS エンドポイントにデータを書き込むシンク実装
Kafka Data Source Apache Kafka トピックからデータを読み取るソース実装
Kafka Data Sink Apache Kafka トピックにデータを書き込むシンク実装
Data Address Validator 転送リクエストに含まれるデータアドレスの形式・接続先の検証
EDR Manager Endpoint Data Reference の管理。Control Plane から受け取った転送パラメーターと認証情報の保持

データ

概念モデル

Provider Catalog Negotiation Transfer Asset DataAddress PolicyDefinition ContractDefinition DataPlaneInstance ContractOffer ContractNegotiation ContractAgreement TransferProcess
要素名 説明
Asset プロバイダーが提供するデータリソースのメタデータ
DataAddress データリソースへの物理的な接続情報
PolicyDefinition アクセス制御ルールの定義 - ODRL 形式
ContractDefinition Asset と Policy を結合するオファーのテンプレート
Catalog コンシューマーに公開されるコントラクトオファーの集合
ContractOffer Catalog に含まれる具体的なオファー
ContractNegotiation コンシューマーとプロバイダー間のネゴシエーション管理
ContractAgreement ネゴシエーション完了後の拘束力ある合意
TransferProcess 合意に基づくデータ転送の実行管理
DataPlaneInstance データ転送を実行するデータプレーンの登録情報

情報モデル

Asset + id: String + createdAt: long + properties: Map + privateProperties: Map + dataAddress: DataAddress DataAddress + type: String + properties: Map Policy + assigner: String + assignee: String + target: String + type: PolicyType + permissions: List + prohibitions: List + obligations: List PolicyDefinition + id: String + createdAt: long + policy: Policy ContractDefinition + id: String + createdAt: long + accessPolicyId: String + contractPolicyId: String + assetsSelector: List ContractNegotiation + id: String + createdAt: long + type: ContractNegotiationType + state: ContractNegotiationState + counterPartyId: String + counterPartyAddress: String + protocol: String + correlationId: String + contractAgreement: ContractAgreement + contractOffers: List ContractAgreement + id: String + providerId: String + consumerId: String + assetId: String + contractSigningDate: long + policy: Policy TransferProcess + id: String + createdAt: long + type: TransferProcessType + state: TransferProcessState + assetId: String + contractId: String + protocol: String + counterPartyAddress: String + contentDataAddress: DataAddress + transferType: String + dataPlaneId: String + privateProperties: Map DataPlaneInstance + id: String + url: URL + state: DataPlaneInstanceState + allowedSourceTypes: Set + allowedTransferTypes: Set + destinationProvisionTypes: Set + properties: Map + labels: Set + lastActive: long contains 1 1 contains 1 1 accessPolicy 1 1 contractPolicy 1 1 assetsSelector 1 * produces 1 1 governs 1 1 covers 1 1 based on * 1 executed by * 1 destination 1 1

エンティティ属性

要素名 属性 説明
Asset id 一意識別子
Asset properties 外部公開メタデータ
Asset privateProperties 内部のみ参照可能なメタデータ
Asset dataAddress データの物理的な場所への参照
DataAddress type プロトコルまたはストレージ種別 - 例: HttpData, AmazonS3
DataAddress properties 接続に必要なエンドポイントや認証情報
Policy permissions 許可ルールのリスト - MAY
Policy prohibitions 禁止ルールのリスト - MUST NOT
Policy obligations 義務ルールのリスト - MUST
Policy type ポリシー種別 - SET / OFFER / CONTRACT
PolicyDefinition id 一意識別子
PolicyDefinition policy ODRL 形式のポリシー本体
ContractDefinition accessPolicyId カタログ閲覧可否を制御するポリシーの参照
ContractDefinition contractPolicyId コントラクト条件を制御するポリシーの参照
ContractDefinition assetsSelector 対象 Asset を絞り込む条件式のリスト
ContractNegotiation type CONSUMER または PROVIDER
ContractNegotiation state 現在の状態
ContractNegotiation counterPartyId 相手方の参加者識別子
ContractNegotiation correlationId 相手方側のネゴシエーション識別子
ContractNegotiation contractAgreement ネゴシエーション完了後に生成される合意
ContractAgreement providerId プロバイダーの参加者識別子
ContractAgreement consumerId コンシューマーの参加者識別子
ContractAgreement assetId 合意対象の Asset 識別子
ContractAgreement contractSigningDate 合意締結のタイムスタンプ
ContractAgreement policy 転送を統制するポリシー
TransferProcess type CONSUMER または PROVIDER
TransferProcess state 現在の状態
TransferProcess assetId 転送対象の Asset 識別子
TransferProcess contractId 根拠となる ContractAgreement の識別子
TransferProcess contentDataAddress 転送先の DataAddress
TransferProcess transferType 転送メカニズムの種別
TransferProcess dataPlaneId 実行を担当する DataPlaneInstance の識別子
DataPlaneInstance url データプレーンのエンドポイント URL
DataPlaneInstance state REGISTERED または UNREGISTERED
DataPlaneInstance allowedSourceTypes 対応可能なソースデータ種別
DataPlaneInstance allowedTransferTypes 対応可能な転送プロトコル種別
DataPlaneInstance destinationProvisionTypes 対応可能な転送先プロビジョニング種別

ContractNegotiation 状態遷移

状態 説明
INITIAL ネゴシエーション開始前
REQUESTING コンシューマーがリクエストを送信中
REQUESTED プロバイダーがリクエストを受信済み
OFFERING プロバイダーがオファーを送信中
OFFERED コンシューマーがオファーを受信済み
ACCEPTING コンシューマーが承諾を送信中
ACCEPTED プロバイダーが承諾を受信済み
AGREEING プロバイダーが合意を送信中
AGREED コンシューマーが合意を受信済み
VERIFYING コンシューマーが検証を送信中
VERIFIED プロバイダーが検証を受信済み
FINALIZING プロバイダーが確定を送信中
FINALIZED コンシューマーが確定を受信済み - ContractAgreement 生成
TERMINATING 終了処理中
TERMINATED ネゴシエーション終了 - 失敗または拒否

TransferProcess 状態遷移

状態 フェーズ 説明
INITIAL 開始 転送プロセス開始前
PROVISIONING プロビジョニング リソースのプロビジョニング中
PROVISIONED プロビジョニング プロビジョニング完了
REQUESTING プロトコル コンシューマーが転送リクエストを送信中
REQUESTED プロトコル プロバイダーがリクエストを受信済み
STARTING プロトコル プロバイダーが転送開始を通知中
STARTED プロトコル 転送実行中
SUSPENDING プロトコル 一時停止処理中
SUSPENDED プロトコル 一時停止中
COMPLETING プロトコル 完了処理中
COMPLETED プロトコル 転送完了
TERMINATING プロトコル 終了処理中
TERMINATED プロトコル 転送終了 - 失敗または中止
DEPROVISIONING デプロビジョニング リソースの解放中
DEPROVISIONED デプロビジョニング リソース解放完了

構築方法

前提条件

項目 要件
Java JDK 17 以上
ビルドツール Gradle - Wrapper 同梱
Docker コンテナ実行時のみ

Java 17 が最低要件です。ビルドツールは Gradle Wrapper(./gradlew)を使用するため、Gradle の個別インストールは不要です。

ソースコード取得とビルド

# リポジトリ取得
git clone https://github.com/eclipse-edc/Connector.git
cd Connector

# ビルド(全モジュール)
./gradlew clean build

Samples リポジトリから特定モジュールのみビルドする場合は以下のとおりです。

git clone https://github.com/eclipse-edc/Samples.git
cd Samples

# 特定モジュールのビルド
./gradlew transfer:transfer-00-prerequisites:connector:build

# JAR の実行
java -jar basic/basic-01-basic-connector/build/libs/basic-connector.jar --log-level=DEBUG

Gradle 依存関係管理 - BOM / Version Catalog

EDC は org.eclipse.edc グループ ID で Maven Central に公開されています。

Version Catalog(推奨)

settings.gradle.kts に BOM を宣言します。

// settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from("org.eclipse.edc:edc-versions:0.14.0")
        }
    }
}

build.gradle.kts での依存関係参照は以下のとおりです。

// build.gradle.kts
dependencies {
    implementation(libs.edc.boot)
    implementation(libs.edc.connector.core)
    implementation(libs.edc.http)
    implementation(libs.edc.configuration.filesystem)
}

Maven の場合

<dependency>
  <groupId>org.eclipse.edc</groupId>
  <artifactId>connector-core</artifactId>
  <version>0.14.0</version>
</dependency>

Extension の作成方法 - SPI 実装

Extension は ServiceExtension インターフェイスを実装して作成します。

1. 依存関係の追加

// build.gradle.kts
dependencies {
    implementation(libs.edc.boot)
    implementation(libs.edc.connector.core)
}

2. Extension クラスの実装

public class HealthEndpointExtension implements ServiceExtension {

    @Inject
    WebService webService;

    @Override
    public void initialize(ServiceExtensionContext context) {
        webService.registerResource(new HealthApiController(context.getMonitor()));
    }
}

3. サービスローダー登録

src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension ファイルに実装クラス名を記載します。

com.example.HealthEndpointExtension

カスタムコネクタの構築

Launcher(実行可能パッケージ)は build.gradle.kts で取り込むモジュールを定義します。

// launcher/build.gradle.kts
plugins {
    `java-library`
    id("application")
    id("com.github.johnrengelman.shadow") version "8.1.1"
}

application {
    mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime")
}

dependencies {
    implementation(libs.edc.boot)
    implementation(libs.edc.connector.core)
    implementation(libs.edc.http)
    implementation(libs.edc.management.api)
    implementation(libs.edc.configuration.filesystem)
    // 追加する機能に応じてモジュールを追加
}
# Fat JAR のビルド
./gradlew launcher:shadowJar
java -jar launcher/build/libs/connector.jar

Docker イメージのビルド

Dockerfile の例

FROM eclipse-temurin:17-jre-alpine
ARG JAR_FILE
COPY ${JAR_FILE} /app/connector.jar
EXPOSE 8181 8182
ENTRYPOINT ["java", "-jar", "/app/connector.jar"]

Docker Compose による Provider / Consumer の起動

services:
  provider:
    build:
      context: .
      target: provider
    ports:
      - "19193:19193"
    volumes:
      - /tmp/provider:/tmp/provider

  consumer:
    build:
      context: .
      target: consumer
    ports:
      - "29193:29193"
    volumes:
      - /tmp/consumer:/tmp/consumer
# コンテナ起動
docker compose up -d

利用方法

API 認証方法

Management API はデフォルトで API Key 認証を使用します。

# ヘッダーに X-Api-Key を付与
curl -H "X-Api-Key: password" ...

設定ファイルで API Key を指定します。

# connector.properties
edc.api.auth.key=password
web.http.management.port=19193
web.http.management.path=/management

Asset 登録

Provider コネクタに Asset を登録します。

curl -X POST http://localhost:19193/management/v3/assets \
  -H 'Content-Type: application/json' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "Asset",
    "@id": "assetId",
    "properties": {
      "name": "product description",
      "contenttype": "application/json"
    },
    "dataAddress": {
      "type": "HttpData",
      "name": "Test asset",
      "baseUrl": "https://jsonplaceholder.typicode.com/users"
    }
  }' -s | jq

Policy 定義

Asset のアクセスルールを ODRL で定義します。

curl -X POST http://localhost:19193/management/v3/policydefinitions \
  -H 'Content-Type: application/json' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "PolicyDefinition",
    "@id": "aPolicy",
    "policy": {
      "@context": "http://www.w3.org/ns/odrl.jsonld",
      "@type": "Set"
    }
  }' -s | jq

Contract Definition 作成

Asset と Policy を紐付けて契約オファーを生成します。

curl -X POST http://localhost:19193/management/v3/contractdefinitions \
  -H 'Content-Type: application/json' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "ContractDefinition",
    "@id": "1",
    "accessPolicyId": "aPolicy",
    "contractPolicyId": "aPolicy",
    "assetsSelector": []
  }' -s | jq

assetsSelector が空の場合、全 Asset が対象です。

Catalog 検索

Consumer が Provider のカタログを取得します。

curl -X POST http://localhost:29193/management/v3/catalog/request \
  -H 'Content-Type: application/json' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "counterPartyAddress": "http://localhost:19194/protocol",
    "protocol": "dataspace-protocol-http"
  }' -s | jq

Contract Negotiation のフロー

Contract Negotiation は非同期の状態機械(State Machine)として処理されます。

ステップ 操作 エンドポイント
1 交渉開始 POST /management/v3/contractnegotiations
2 状態確認 GET /management/v3/contractnegotiations/{id}
3 合意 ID 取得 状態が FINALIZED になったら contractAgreementId を記録

交渉開始

curl -X POST http://localhost:29193/management/v3/contractnegotiations \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: password' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "ContractRequest",
    "counterPartyAddress": "http://localhost:19194/protocol",
    "protocol": "dataspace-protocol-http",
    "policy": {
      "@context": "http://www.w3.org/ns/odrl.jsonld",
      "@type": "Offer",
      "@id": "<catalog から取得した offer ID>",
      "assigner": "<provider ID>",
      "target": "assetId"
    }
  }' -s | jq

状態確認

# {negotiation_id} は交渉開始レスポンスの @id
curl http://localhost:29193/management/v3/contractnegotiations/{negotiation_id} \
  -H 'X-Api-Key: password' -s | jq

状態遷移の流れは REQUESTINGREQUESTEDAGREEDVERIFIEDFINALIZED です。

Transfer Process の開始

Contract Agreement 取得後、データ転送を開始します。

curl -X POST http://localhost:29193/management/v3/transferprocesses \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: password' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "TransferRequest",
    "counterPartyAddress": "http://localhost:19194/protocol",
    "contractId": "<contractAgreementId>",
    "assetId": "assetId",
    "protocol": "dataspace-protocol-http",
    "transferType": "HttpData-PULL"
  }' -s | jq

状態が STARTED になったら、EDR(EndpointDataReference)を取得してデータにアクセスします。

EDR によるデータアクセス(Consumer Pull)

# 1. EDR 取得(アクセストークン含む)
curl http://localhost:29193/management/v3/edrs/{transfer_id}/dataaddress \
  -H 'X-Api-Key: password' -s | jq

# 2. EDR のエンドポイントとトークンでデータ取得
curl -H "Authorization: <EDR の authorization 値>" \
  "<EDR の endpoint 値>" -s | jq

データ転送パターン

EDC は複数のデータ転送パターンを提供します。transferType フィールドで指定します。

transferType 転送方向 説明
HttpData-PULL Consumer Pull コンシューマがプロバイダの Data Plane Public API から HTTP でデータを取得
HttpData-PUSH Provider Push プロバイダがコンシューマ指定の HTTP エンドポイントにデータを送信
AmazonS3-PUSH Provider Push プロバイダがコンシューマ指定の S3 バケットにデータを転送
AzureStorage-PUSH Provider Push プロバイダがコンシューマ指定の Azure Blob Storage にデータを転送
Kafka-PUSH Streaming プロバイダが Kafka トピック経由でストリームデータを配信

パターン比較

観点 Consumer Pull Provider Push Streaming
能動側 コンシューマ プロバイダ プロバイダ
転送タイミング コンシューマ任意 コントラクト確立後に即時 継続的
転送プロセス最終状態 STARTED 継続 COMPLETED TERMINATED
EDR の利用 必須 不要 不要
主なユースケース REST API スタイルのデータ取得 ファイル・バッチ転送 リアルタイムイベント

Consumer Pull パターン - HttpData-PULL

コンシューマが能動的にデータを取得するパターンです。コントラクト交渉完了後、EDR(Endpoint Data Reference)を取得し、そのトークンを用いて Data Plane の Public API に直接アクセスします。

  • コンシューマとプロバイダの双方の Control Plane がトークンに署名するため、プロバイダへの直接アクセスが防止されます
  • proxyPathproxyQueryParamsproxyMethodproxyBody の設定により、REST API のように柔軟にデータを取得できます
  • 転送プロセスは STARTED 状態のまま継続し、1 つのコントラクトに対して複数回のデータ取得が可能です

Provider Push パターン - HttpData-PUSH

プロバイダが能動的にコンシューマ指定のエンドポイントにデータを送信するパターンです。

curl -X POST http://localhost:29193/management/v3/transferprocesses \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: password' \
  -d '{
    "@context": {
      "@vocab": "https://w3id.org/edc/v0.0.1/ns/"
    },
    "@type": "TransferRequest",
    "counterPartyAddress": "http://localhost:19194/protocol",
    "contractId": "<contractAgreementId>",
    "assetId": "assetId",
    "protocol": "dataspace-protocol-http",
    "transferType": "HttpData-PUSH",
    "dataDestination": {
      "type": "HttpData",
      "baseUrl": "http://consumer-backend:4000/receiver"
    }
  }' -s | jq
  • 有限転送(1 回送信後に終了)と無限転送(手動停止まで継続)の 2 種類があります
  • AmazonS3-PUSH、AzureStorage-PUSH も同じフローで、DataSink の実装が置き換わります

EDR - Endpoint Data Reference の仕組み

EDR は Consumer Pull パターンで中心的な役割を果たすデータアクセス参照情報です。

{
  "@type": "DataAddress",
  "type": "https://w3id.org/idsa/v4.1/HTTP",
  "endpoint": "http://provider-data-plane:19291/public",
  "authType": "bearer",
  "authorization": "<JWT トークン>"
}
特性 説明
ネストされたトークン構造 プロバイダとコンシューマ双方が署名し、プロバイダへの直接アクセスを防止
トークン有効期限 デフォルト 10 分 - 設定変更可能
トークンローテーション Tractus-X 実装ではリフレッシュトークンにより対応
ポリシー強制 アクセス都度 Control Plane でコントラクト有効性を確認

主要 Management API エンドポイント一覧

リソース メソッド パス
Asset 作成 POST /management/v3/assets
Policy 作成 POST /management/v3/policydefinitions
Contract Definition 作成 POST /management/v3/contractdefinitions
Catalog 取得 POST /management/v3/catalog/request
Contract Negotiation 開始 POST /management/v3/contractnegotiations
Contract Negotiation 状態確認 GET /management/v3/contractnegotiations/{id}
Transfer Process 開始 POST /management/v3/transferprocesses
Transfer Process 状態確認 GET /management/v3/transferprocesses/{id}
EDR 取得 GET /management/v3/edrs/{id}/dataaddress

運用

デプロイメントパターン

Docker Compose - 開発・検証用

services:
  controlplane:
    image: <your-image>/controlplane:latest
    ports:
      - "8181:8181"  # API / Health Check
      - "8080:8080"  # Management API
      - "8084:8084"  # DSP Protocol
    environment:
      - EDC_VAULT_HASHICORP_URL=http://vault:8200
      - EDC_VAULT_HASHICORP_TOKEN=<token>
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8181/api/check/health"]
      interval: 5s
      timeout: 5s
      retries: 10

  prometheus:
    image: prom/prometheus:v2.30.3
    volumes:
      - ./prometheus/:/etc/prometheus/
    ports:
      - "9090:9090"

Kubernetes - 本番用

Tractus-X EDC の Helm チャートを利用するのが推奨パターンです。

# 名前空間作成(参加者分離)
kubectl create ns provider
kubectl create ns consumer

# Helm でコネクター展開
git clone https://github.com/eclipse-tractusx/tractusx-edc
cd tractusx-edc/charts/tractusx-connector
helm dependency build
helm upgrade --install provider ./ -f provider_edc.yaml -n provider
helm upgrade --install consumer ./ -f consumer_edc.yaml -n consumer

エンドポイント構成(Control Plane)

用途 ポート パス
Management API 8081 /management
Control 8083 /control
DSP Protocol 8084 /api/v1/dsp
Metrics 9090 /metrics
Observability 8085 /observability

エンドポイント構成(Data Plane)

用途 ポート パス
Default 8080 /api
Public 8081 /api/dataplane/control
Proxy 8186 /proxy
Metrics 9090 /metrics

クラウド別実装

AWS

サービス 用途
Amazon EKS EDC コネクター実行 - Kubernetes
Amazon RDS - PostgreSQL コネクター状態の永続化
Amazon S3 データ転送ソース・宛先
AWS Secrets Manager / HashiCorp Vault シークレット管理

S3 アセット登録の例

{
  "dataAddress": {
    "edc:type": "AmazonS3",
    "name": "Vehicle Carbon Footprint",
    "bucketName": "<BUCKET_NAME>",
    "keyName": "carbon_data.json",
    "region": "eu-west-1",
    "accessKeyId": "<ACCESS_KEY>",
    "secretAccessKey": "<SECRET_KEY>"
  }
}

Azure

サービス 役割
Azure CosmosDB 各種ストレージバックエンド
Azure Key Vault 暗号鍵・シークレット管理
Azure Blob Storage データ転送ストレージ
Azure Application Insights メトリクス・トレース可視化
edc.vault.azure.name=<vault-name>
edc.vault.azure.client.id=<client-id>
edc.vault.azure.tenant.id=<tenant-id>
edc.vault.azure.client.secret=<secret>

GCP

GCP 向けは GKE + Cloud SQL(PostgreSQL) + Cloud Storage の組み合わせが一般的です。

Identity Hub のデプロイ

# Java プロセスとして起動
java -Dweb.http.credentials.port=10001 \
     -Dweb.http.credentials.path="/api/credentials" \
     -Dweb.http.port=8181 \
     -Dweb.http.path="/api" \
     -Dweb.http.identity.port=8182 \
     -Dweb.http.identity.path="/api/identity" \
     -jar launcher/identityhub/build/libs/identity-hub.jar
# Docker コンテナとして起動
docker run -d --rm --name identityhub \
    -e "WEB_HTTP_IDENTITY_PORT=8182" \
    -e "WEB_HTTP_IDENTITY_PATH=/api/identity" \
    -e "WEB_HTTP_PRESENTATION_PORT=10001" \
    -e "WEB_HTTP_PRESENTATION_PATH=/api/presentation" \
    -e "EDC_IAM_STS_PRIVATEKEY_ALIAS=privatekey-alias" \
    -e "EDC_IAM_STS_PUBLICKEY_ID=publickey-id" \
    identity-hub:latest

監視・オブザーバビリティ

ヘルスチェックエンドポイント

エンドポイント 用途
GET /api/check/health システム全体の状態 - Docker HEALTHCHECK 向け
GET /api/check/liveness コンテナ動作確認
GET /api/check/readiness リクエスト受け付け可能確認
GET /api/check/startup アプリケーション起動完了確認

OpenTelemetry による分散トレーシング

# Docker Compose 環境変数
environment:
  - OTEL_SERVICE_NAME=edc-controlplane
  - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317
  - OTEL_METRICS_EXPORTER=prometheus
  - JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar

Micrometer によるメトリクス収集

カテゴリ メトリクス
JVM ヒープメモリ、GC、スレッド数、クラスローダー
HTTP クライアント - OkHttp リクエスト数、レイテンシ - URL 別
HTTP サーバー - Jetty 接続数、入出力バイト数
REST エンドポイント - Jersey リクエスト数、レイテンシ - ステータスコード・例外別
スレッドプール アイドル・アクティブスレッド数、キュー待ちタスク数

セキュリティ設定

HashiCorp Vault 連携

パラメーター 説明 デフォルト
edc.vault.hashicorp.url Vault サーバー URL なし - 必須
edc.vault.hashicorp.token トークン認証資格情報 なし - 必須
edc.vault.hashicorp.timeout.seconds リクエストタイムアウト 30
edc.vault.hashicorp.health.check.enabled ヘルスチェック有効化 true
edc.vault.hashicorp.url=https://vault.example.com
edc.vault.hashicorp.token=<token>
edc.vault.hashicorp.api.secret.path=/v1/edc/
edc.vault.hashicorp.health.check.standby.ok=true

スケーリング戦略

原則 内容
非同期性 状態変更はすべて非同期・永続的に実行
ステートレス Data Plane データプレーンはステートレス設計のため水平スケールが可能
ステートフル Control Plane 悲観的ロック付きシーケンシャルステートマシンで動作
エラー耐性 低レイテンシより信頼性を優先し、一時的エラーを吸収

Data Plane はステートレス設計のため、レプリカ数を増やすだけでスケールアウトできます。Control Plane は PostgreSQL を共有ストアとして使用し、アクティブ-スタンバイ構成が推奨です。

ベストプラクティス

Extension 開発

  • Extension は ServiceExtension インターフェースを実装します
  • @Provider メソッドでサービスを公開します
  • @Inject アノテーションで依存サービスを宣言します
  • 拡張の発見はクラスパススキャンで自動的に行われます
public class MyExtension implements ServiceExtension {

    @Inject
    private AssetService assetService;

    @Provider
    public MyService myService() {
        return new MyServiceImpl(assetService);
    }

    @Override
    public void initialize(ServiceExtensionContext context) {
        var setting = context.getSetting("my.setting", "defaultValue");
    }
}

設定管理

  • 設定は @Setting アノテーションで型安全に定義します
  • プロパティ名は edc.* 命名規則に従います
  • ServiceExtensionContext.getSetting() でアクセスします

非同期処理

  • 内部状態変更はすべて非同期で行います
  • REST リクエストはトリガーのみで、状態変更自体は非同期ステートマシンが処理します
  • 冪等性を確保します(外部リソースプロビジョニング含む)

ポリシー設計パターン

アクセスポリシーとコントラクトポリシーの使い分け

項目 アクセスポリシー コントラクトポリシー
評価タイミング カタログ生成時 契約ネゴシエーション時・転送開始前
目的 アセットをカタログに表示するかの制御 契約締結・データ利用の条件制御
ODRL action access use

ODRL 制約パターンのバリエーション

制約種別 leftOperand 用途
BPN 制約 BusinessPartnerNumber 特定のビジネスパートナーにのみアクセス許可
グループ制約 BusinessPartnerGroup BPN をグループ単位で管理
メンバーシップ Membership メンバーシップ保有者にのみ許可
時間制限 inForceDate データ利用の有効期限
地域制限 location 特定地域のパートナーにのみ許可
ロール制約 Dismantler 参加者のロール情報で制約
フレームワーク合意 FrameworkAgreement 特定の合意への同意を必須化

BusinessPartnerNumber による制約例

{
  "@type": "PolicyDefinition",
  "@id": "bpn-policy",
  "policy": {
    "@type": "Set",
    "permission": [
      {
        "action": "use",
        "constraint": {
          "leftOperand": "BusinessPartnerNumber",
          "operator": "eq",
          "rightOperand": "BPNL00000000XXXX"
        }
      }
    ]
  }
}

時間制限(利用期限)の例

{
  "permission": [
    {
      "action": "use",
      "constraint": {
        "leftOperand": "inForceDate",
        "operator": "lteq",
        "rightOperand": "2026-12-31T23:59:59Z"
      }
    }
  ]
}

AND 条件の組み合わせ例

{
  "permission": [
    {
      "action": "use",
      "constraint": {
        "@type": "AndConstraint",
        "and": [
          {
            "leftOperand": "FrameworkAgreement",
            "operator": "eq",
            "rightOperand": "DataExchangeGovernance:1.0"
          },
          {
            "leftOperand": "Membership",
            "operator": "eq",
            "rightOperand": "active"
          }
        ]
      }
    }
  ]
}

カスタムポリシー関数の登録

カスタム制約は AtomicConstraintRuleFunction を実装し、PolicyEngine に登録します。

public class LocationConstraintFunction implements
    AtomicConstraintRuleFunction<Permission, ContractNegotiationPolicyContext> {

    @Override
    public boolean evaluate(Operator operator, Object rightValue,
        Permission rule, ContractNegotiationPolicyContext context) {
        var region = context.participantAgent().getClaims().get("region");
        return switch (operator) {
            case EQ  -> Objects.equals(region, rightValue);
            case NEQ -> !Objects.equals(region, rightValue);
            case IN  -> ((Collection<?>) rightValue).contains(region);
            default  -> false;
        };
    }
}

Extension での登録

public class MyPolicyExtension implements ServiceExtension {

    @Inject
    private RuleBindingRegistry ruleBindingRegistry;

    @Inject
    private PolicyEngine policyEngine;

    @Override
    public void initialize(ServiceExtensionContext context) {
        // ルールをスコープにバインド
        ruleBindingRegistry.bind("use", ALL_SCOPES);
        ruleBindingRegistry.bind("location", NEGOTIATION_SCOPE);

        // 関数を PolicyEngine に登録
        policyEngine.registerFunction(
            ContractNegotiationPolicyContext.class,
            Permission.class,
            "location",
            new LocationConstraintFunction()
        );
    }
}

ポリシースコープの種類

スコープ 評価タイミング
contract.cataloging カタログ生成時 - アセットの可視性フィルタリング
contract.negotiation 契約ネゴシエーション時
contract.agreement 契約合意評価時
transfer.process データ転送開始前の再評価

注意: EDC のポリシーエンジンは評価できないポリシーをデフォルトで true(許可)として扱います。カスタム制約関数の登録漏れが意図せぬアクセス許可につながるため、本番環境では必ずポリシーバリデーションを有効化してください。

テスト戦略

レイヤー ツール 用途
ユニットテスト JUnit 5 + Mockito 単一クラスの動作検証
Controller 統合テスト Jersey + RestAssured API エンドポイント検証
ランタイム統合テスト EdcRuntimeExtension 複数 Runtime を起動した E2E 検証
非同期テスト Awaitility 非同期状態変更の検証
プロトコル適合テスト DSP TCK / DCP TCK プロトコル準拠確認

バージョン管理・アップグレード

  1. Releases ページで対象バージョンの変更点を確認します
  2. 廃止予定 API の使用箇所を特定します
  3. ローカル環境で統合テストを実行して動作を確認します
  4. ステージング環境で E2E テストを実施します
  5. 本番環境へデプロイします

トラブルシューティング

Contract Negotiation の失敗パターン

ポリシー不一致エラー

症状: Policy in the contract agreement is not equal to the one in the contract offer

対処:

  • policy.permission.targetnull で送信するか、アセットポリシーと完全一致させます
  • Management API でアセットのポリシー定義を確認します

状態確認

curl -X GET http://localhost:8081/management/v2/contractnegotiations/<negotiation-id> \
  -H "x-api-key: <api-key>"

Transfer Process のエラーハンドリング

409 エラー: アグリーメントが見つからない

症状: Cannot process TransferRequestMessage because agreement not found or not valid

対処:

  • format パラメーターが <destination_type>-<flow_type> 形式(例: HttpData-PULL)か確認します
  • Management API 経由でアグリーメント ID の存在を確認します

ログ確認とデバッグ手順

# Kubernetes でのログ確認
kubectl logs -n provider deployment/provider-tractusx-connector-controlplane -f
kubectl logs -n provider deployment/provider-tractusx-connector-dataplane -f

# ヘルスチェック
curl http://localhost:8181/api/check/health

よくあるエラーと対処法一覧

エラー 原因 対処
ポリシー不一致 Contract Offer とネゴシエーション時のポリシーが異なる permission.target を null にするかポリシーを統一
409 Agreement not found format パラメーター形式の誤り HttpData-PULL 等の正しい形式を使用
Vault ヘルスチェック失敗 スタンバイ Vault を unhealthy と判定 health.check.standby.ok=true を設定
Data Plane 起動失敗 No data flow controller found Data Plane Selector 拡張の設定を確認
無限ループ - Contract Negotiation プロセスの中断 コネクターを再起動してステートマシンを回復

コミュニティサポート

チャンネル 用途
Discord 使い方の質問、一般的なディスカッション
GitHub Discussions コードベースの質問、新機能の検討
GitHub Issues バグ報告 - 再現手順を含むこと

まとめ

Eclipse EDC は、IDSA DSP 標準に準拠し、データ主権を保ったまま組織間のデータ共有を実現するオープンソースフレームワークです。制御プレーンとデータプレーンの分離設計、ODRL ベースのポリシーエンジン、モジュラーな拡張アーキテクチャにより、マルチクラウド環境でも柔軟にデータスペースを構築できます。Catena-X をはじめとする産業データスペースの参照実装として、今後さらに適用分野が広がることが期待されます。

この記事が少しでも参考になった、あるいは改善点などがあれば、ぜひリアクションやコメント、SNSでのシェアをいただけると励みになります!

参考リンク