Skip to content

Commit

Permalink
feat: docker_compose with ngrok
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Burdett <[email protected]>
  • Loading branch information
burdettadam committed Nov 8, 2023
1 parent f96d3e2 commit fbb9b4d
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 98 deletions.
14 changes: 9 additions & 5 deletions oid4vci/demo/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ services:
- "3000:3000"
- "3001:3001"
- "8081:8081"
volumes:
- ../docker/entrypoint.sh:/entrypoint.sh:ro,z
environment:
RUST_LOG: warn
TUNNEL_ENDPOINT: http://ngrok:4040
entrypoint: >
/bin/sh -c '/entrypoint.sh aca-py "$$@"' --
command: >
start
--inbound-transport http 0.0.0.0 3000
Expand Down Expand Up @@ -45,6 +50,8 @@ services:
condition: service_started
tails:
condition: service_started
ngrok:
condition: service_healthy

webhook-listener:
image: mendhak/http-https-echo:18
Expand All @@ -65,15 +72,12 @@ services:
--log-level INFO
ngrok:
#image: ngrok/ngrok
image: wernight/ngrok
image: ngrok/ngrok
restart: unless-stopped
hostname: ngrok
volumes:
- ./ngrok.yml:/home/ngrok/.ngrok2/ngrok.yml:z
ports:
- "4040:4040"
command: ["ngrok", "http", "oid4vci:8001"]
command: ["http", "issuer:8081"]
healthcheck:
test: /bin/bash -c "</dev/tcp/ngrok/4040"
interval: 3s
Expand Down
32 changes: 20 additions & 12 deletions oid4vci/demo/frontend/src/FormPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ const FormPage = () => {
};

const handleSubmit = () => {
console.log(
`/qr-code/${firstName}/${lastName}/${email}/${selectedCredential}`
);
// Set the Axios configuration for CORS and credentials
axios.defaults.withCredentials = true; // Enable credentials (cookies, etc.)
axios.defaults.headers.common['Access-Control-Allow-Origin'] = 'http://localhost:3001'; // Adjust the origin as needed
Expand All @@ -34,12 +31,23 @@ const FormPage = () => {
credential_supported_id: selectedCredential,
})
.then((response) => {
// TODO: call offer endpoint
console.log(response.data);
const credentialOffer = response.data.offer;
const {exchange_id} = response.data;
navigate(`/qr-code`, { state: { credentialOffer, exchange_id: exchange_id } });
})
const {exchange_id} = response.data
// TODO: call offer endpoint

const queryParams = {
credentials: [selectedCredential],
user_pin_required: false,
exchange_id: exchange_id,
};
axios.get("http://localhost:3001/oid4vci/draft-11/credential-offer", { params: queryParams })
.then((response) => {
console.log(response.data);
const credentialOffer = response.data;
const {exchange_id} = response.data;
navigate(`/qr-code`, { state: { credentialOffer, exchange_id: exchange_id } });
})
})
.catch((error) => {
console.error(error);
});
Expand All @@ -61,15 +69,15 @@ const FormPage = () => {
src={img2}
width={250}
height={150}
alt="Credential 2"
onClick={() => handleCredentialSelect("Credential 2")}
alt="UniversityDegreeCredential"
onClick={() => handleCredentialSelect("UniversityDegreeCredential")}
/>
<img
src={img3}
width={250}
height={150}
alt="Credential 3"
onClick={() => handleCredentialSelect("Credential 3")}
alt="UniversityDegreeCredential"
onClick={() => handleCredentialSelect("UniversityDegreeCredential")}
/>
</div>
<button onClick={handleSubmit}>Submit</button>
Expand Down
4 changes: 2 additions & 2 deletions oid4vci/demo/frontend/src/QRCodePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ const QRCodePage = () => {
axios.defaults.headers.common['Access-Control-Allow-Origin'] = 'http://localhost:3001'; // Adjust the origin as needed

axios
.get(`http://localhost:3001/oid4vci/exchange/records/${exchange_id}`, {})
.get(`http://localhost:3001/oid4vci/exchange/records`, {exchange_id: exchange_id})
.then((response) => {
console.log(response.data);
if(response.data === "completed"){
if(response.data.state === "completed"){
navigate(`/`);
}
})
Expand Down
2 changes: 0 additions & 2 deletions oid4vci/demo/ngrok.yml

This file was deleted.

5 changes: 3 additions & 2 deletions oid4vci/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ USER root

ENV POETRY_VERSION=1.4.2
ENV POETRY_HOME=/opt/poetry
RUN apt-get update && apt-get install -y curl && apt-get clean
RUN apt-get update && apt-get install -y curl jq && apt-get clean
RUN curl -sSL https://install.python-poetry.org | python -

ENV PATH="/opt/poetry/bin:$PATH"
Expand All @@ -19,10 +19,11 @@ RUN poetry install --without dev
USER $user

FROM python:3.9-bullseye

WORKDIR /usr/src/app
COPY --from=base /usr/src/app/.venv /usr/src/app/.venv
ENV PATH="/usr/src/app/.venv/bin:$PATH"

RUN apt-get update && apt-get install -y curl jq && apt-get clean
COPY oid4vci/ oid4vci/
COPY docker/*.yml ./

Expand Down
47 changes: 47 additions & 0 deletions oid4vci/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash

TUNNEL_ENDPOINT=${TUNNEL_ENDPOINT:-http://localhost:4040}

WAIT_INTERVAL=${WAIT_INTERVAL:-3}
WAIT_ATTEMPTS=${WAIT_ATTEMPTS:-10}

liveliness_check () {
for CURRENT_ATTEMPT in $(seq 1 "$WAIT_ATTEMPTS"); do
if ! curl -s -o /dev/null -w '%{http_code}' "${1}/status" | grep "200" > /dev/null; then
if [[ $CURRENT_ATTEMPT -gt $WAIT_ATTEMPTS ]]
then
echo "Failed while waiting for 200 status from ${1}"
exit 1
fi

echo "Waiting for tunnel..." 1>&2
sleep "$WAIT_INTERVAL" &
wait $!
else
break
fi
done
}

liveliness_check "${TUNNEL_ENDPOINT}"

# Capture the JSON response from the endpoint
RESPONSE=$(curl --silent "${TUNNEL_ENDPOINT}/api/tunnels/command_line")
# Print the response for debugging purposes
# echo "JSON Response: $RESPONSE"

if [[ $RESPONSE == *"\"public_url\""* ]]; then

# Extract the public URL
public_url=$(echo "$RESPONSE" | jq -r '.public_url')
echo "public_url: $public_url"

# Set it as an environment variable
export OID4VCI_ENDPOINT="$public_url"

# Execute the provided command (arguments)
exec "$@"
else
echo "Failed to retrieve public URL from ngrok"
exit 1
fi
14 changes: 11 additions & 3 deletions oid4vci/oid4vci/v1_0/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import logging
from os import getenv

from aries_cloudagent.config.injection_context import InjectionContext
from aries_cloudagent.core.event_bus import Event, EventBus
from aries_cloudagent.core.profile import Profile
from aries_cloudagent.protocols.endorse_transaction.v1_0.routes import (
STARTUP_EVENT_PATTERN,
)

from oid4vci.v1_0.oid4vci_server import Oid4vciServer

LOGGER = logging.getLogger(__name__)

OID4VCI_HOST = getenv("OID4VCI_HOST", default="0.0.0.0")
OID4VCI_PORT: str = getenv("OID4VCI_PORT", default="8081")


async def setup(context: InjectionContext):
"""Setup the plugin."""
Expand All @@ -28,8 +31,13 @@ async def started_event_handler(profile: Profile, event: Event):
"""Event handler for Basic Messages."""
LOGGER.info(event.payload)
try:
host = profile.context.settings.get("oid4vci.host", "0.0.0.0")
port = profile.context.settings.get("oid4vci.port", "8081")
# -o oid4vci.host=0.0.0.0 -o oid4vci.port=8081
plugin_settings = profile.context.settings.for_plugin("oid4vci")
host = plugin_settings.get("host") or OID4VCI_HOST
port = plugin_settings.get("port") or OID4VCI_PORT
assert host
assert port

oid4vci = Oid4vciServer(
host,
port,
Expand Down
11 changes: 8 additions & 3 deletions oid4vci/oid4vci/v1_0/models/cred_ex_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ class OID4VCICredentialExchangeRecord(BaseExchangeRecord):
class Meta:
schema_class = "CredExRecordSchema"

RECORD_ID_NAME = "oid4vci_ex_id"
RECORD_ID_NAME = "oid4vci_x_id"
RECORD_TYPE = "oid4vci"
EVENT_NAMESPACE = "oid4vci"
RECORD_TOPIC = "oid4vci"
EVENT_NAMESPACE = "acapy"
TAG_NAMES = {"nonce", "pin", "token"}

def __init__(
self,
*,
oid4vci_x_id=None,
credential_supported_id=None,
credential_subject: Optional[Dict[str, Any]] = None,
nonce=None,
Expand All @@ -27,7 +29,7 @@ def __init__(
**kwargs,
):
super().__init__(
None,
oid4vci_x_id,
state="init",
**kwargs,
)
Expand All @@ -43,6 +45,9 @@ def credential_exchange_id(self) -> str:
"""Accessor for the ID associated with this exchange."""
return self._id

def dump(self):
return vars(self)


# TODO: add validation
class CredExRecordSchema(BaseRecordSchema):
Expand Down
35 changes: 16 additions & 19 deletions oid4vci/oid4vci/v1_0/models/cred_sup_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,27 @@ class OID4VCICredentialSupported(BaseRecord):
class Meta:
schema_class = "CredSupRecordSchema"

RECORD_ID_NAME = "oid4vci_id"
RECORD_ID_NAME = "oid4vci_cred_id"
RECORD_TYPE = "oid4vci_exchange"
EVENT_NAMESPACE = "oid4vci"
TAG_NAMES = {"credential_supported_id", "types", "scope"}

def __init__(
self,
*,
credential_supported_id,
format,
types,
cryptographic_binding_methods_supported,
cryptographic_suites_supported,
display,
credential_subject,
scope,
oid4vci_cred_id=None,
credential_supported_id=None,
format=None,
types=None,
cryptographic_binding_methods_supported=None,
cryptographic_suites_supported=None,
display=None,
credential_subject=None,
scope=None,
**kwargs,
):
super().__init__(
None,
oid4vci_cred_id,
state="init",
**kwargs,
)
Expand Down Expand Up @@ -53,20 +54,19 @@ class CredSupRecordSchema(BaseRecordSchema):
class Meta:
model_class = OID4VCICredentialSupported

credential_supported_id = fields.Str(
required=True, metadata={"example": "UniversityDegree_JWT"}
scope = fields.Str(
required=True, metadata={"example": "UniversityDegreeCredential"}
)
format = fields.Str(required=True, metadata={"example": "jwt_vc_json"})
types = fields.List(
fields.Str(),
metadata={"example": ["VerifiableCredential", "UniversityDegreeCredential"]},
)
cryptographic_binding_methods_supported = fields.List(
fields.Str(), metadata={"example": []}
)
cryptographic_suites_supported = fields.List(
fields.Str(), metadata={"example": ["ES256K"]}
)
proof_types_supported = fields.List(
fields.Str(), metadata={"example": ["Ed25519Signature2018"]}
)
display = fields.List(
fields.Dict(),
metadata={
Expand All @@ -92,6 +92,3 @@ class Meta:
"gpa": {"display": [{"name": "GPA"}]},
}
)
scope = fields.Str(
required=True,
)
19 changes: 12 additions & 7 deletions oid4vci/oid4vci/v1_0/public_routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Public routes for OID4VCI."""

import logging
from os import getenv
from typing import Optional
from aries_cloudagent.core.profile import Profile
import jwt as pyjwt
Expand All @@ -17,6 +18,8 @@
from .models.cred_sup_record import OID4VCICredentialSupported

LOGGER = logging.getLogger(__name__)
OID4VCI_ENDPOINT = getenv("OID4VCI_ENDPOINT")
assert OID4VCI_ENDPOINT


class IssueCredentialRequestSchema(OpenAPISchema):
Expand Down Expand Up @@ -54,11 +57,11 @@ class GetTokenSchema(OpenAPISchema):


@docs(tags=["oid4vci"], summary="Get credential issuer metadata")
@querystring_schema(TokenRequestSchema())
# @querystring_schema(TokenRequestSchema())
async def oid_cred_issuer(request: web.Request):
"""Credential issuer metadata endpoint."""
profile = request["context"].profile
public_url = profile.context.settings.get("public_url") # TODO: check
public_url = OID4VCI_ENDPOINT # TODO: check for flag first

# Wallet query to retrieve credential definitions
tag_filter = {"type": {"$in": ["sd_jwt", "jwt_vc_json"]}}
Expand All @@ -68,7 +71,7 @@ async def oid_cred_issuer(request: web.Request):
)

metadata = {
"credential_issuer": f"{public_url}/issuer",
"credential_issuer": f"{public_url}/", # TODO: update path with wallet id
"credential_endpoint": f"{public_url}/credential",
"credentials_supported": [cred.serialize() for cred in credentials_supported],
"authorization_server": f"{public_url}/auth-server",
Expand Down Expand Up @@ -119,9 +122,11 @@ async def register(app: web.Application):
oid_cred_issuer,
allow_head=False,
),
# web.get("/.well-known/", self., allow_head=False),
# web.get("/.well-known/", self., allow_head=False),
web.post("/credential", issue_cred),
web.post("/token", get_token),
# web.get("/auth-server/.well-known/oauth-authorization-server", self., allow_head=False),
# web.get("/auth-server/.well-known/openid-configuration", self., allow_head=False),
web.post("/draft-13/credential", issue_cred),
web.post("/draft-11/credential", issue_cred),
web.post("/draft-13/token", get_token),
web.post("/draft-11/token", get_token),
]
)
Loading

0 comments on commit fbb9b4d

Please sign in to comment.