Skip to content

Commit 87b5523

Browse files
committed
Merge branch 'deployment' into ethr-integration
2 parents 1b7defb + d4d7edf commit 87b5523

File tree

7 files changed

+180
-19
lines changed

7 files changed

+180
-19
lines changed

.github/workflows/prod.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Build and deploy CREDO STAGE to ECS
33
on:
44
push:
55
tags:
6-
- 'prod*'
6+
- 'pr'
77

88

99
env:

.github/workflows/qa.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Build and deploy credo on QA
33
on:
44
push:
55
tags:
6-
- 'qa*'
6+
- 'qa-*'
77

88

99
env:
@@ -25,8 +25,13 @@ jobs:
2525
- name: Checkout Repository
2626
uses: actions/checkout@v2
2727

28+
- name: Set up Node.js
29+
uses: actions/setup-node@v3
30+
with:
31+
node-version: 18.19.0
32+
2833
- name: Set up Docker Buildx
29-
uses: docker/setup-buildx-action@v1
34+
uses: docker/setup-buildx-action@v3
3035

3136
- name: Configure AWS Credentials
3237
uses: aws-actions/configure-aws-credentials@v3
@@ -47,9 +52,12 @@ jobs:
4752
ECR_REPOSITORY: qa-services
4853
IMAGE_TAG: "CREDO_V_${{ github.run_number }}"
4954
run: |
50-
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
55+
docker buildx build \
56+
--platform linux/amd64 \
57+
--output type=docker \
58+
-t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
59+
5160
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
52-
docker image list
5361
5462
- name: Set environment variables
5563
run: |
@@ -80,15 +88,15 @@ jobs:
8088
echo "SERVICE_NAME: $SERVICE_NAME"
8189
8290
# Replace placeholders in the JSON file
83-
sed -e "s;%BUILD_NUMBER%;${{ github.run_number }};g" -e "s;%REPOSITORY_URI%;${REPOSITORY_URI};g" taskdef/qa-credo-service.json > ${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json
91+
sed -e "s;%BUILD_NUMBER%;${{ github.run_number }};g" -e "s;%REPOSITORY_URI%;${REPOSITORY_URI};g" taskdef/qa-credo-service.json > "${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json"
8492
8593
# Debug: Print the content of the modified JSON file
86-
cat ${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json
94+
cat "${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json"
8795

8896
# Register the task definition using the modified JSON file
89-
aws ecs register-task-definition --family ${FAMILY} --cli-input-json file://${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json --region ${{ env.AWS_REGION }}
97+
aws ecs register-task-definition --family "${FAMILY}" --cli-input-json file://"${GITHUB_WORKSPACE}/${NAME}-v_${{ github.run_number }}.json" --region "${{ env.AWS_REGION }}"
9098

91-
SERVICE_INFO=$(aws ecs describe-services --services ${SERVICE_NAME} --cluster ${CLUSTER} --region ap-southeast-1)
99+
SERVICE_INFO=$(aws ecs describe-services --services "${SERVICE_NAME}" --cluster "${CLUSTER}" --region ap-southeast-1)
92100

93101
# Check if the service exists
94102
if [ -z "$SERVICE_INFO" ]; then

.github/workflows/stage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Build and deploy CREDO STAGE to ECS
33
on:
44
push:
55
tags:
6-
- 'stage*'
6+
- 'st'
77

88
env:
99

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ RUN yarn global add patch-package
6363
RUN yarn build
6464

6565
# Stage 2: Production stage
66-
FROM node:18.19.0-slim
66+
FROM node:18.19.0-slim AS runtime
6767

6868
WORKDIR /app
6969

src/controllers/multi-tenancy/MultiTenancyController.ts

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import type { RestAgentModules, RestMultiTenantAgentModules } from '../../cliAgent'
22
import type { Version } from '../examples'
3-
import type { RecipientKeyOption, SchemaMetadata } from '../types'
3+
import type {
4+
CustomW3cJsonLdSignCredentialOptions,
5+
RecipientKeyOption,
6+
SafeW3cJsonLdVerifyCredentialOptions,
7+
SchemaMetadata,
8+
SignDataOptions,
9+
} from '../types'
410
import type { EthereumDidCreateOptions } from '@ayanworks/credo-ethr-module/build/dids'
511
import type { PolygonDidCreateOptions } from '@ayanworks/credo-polygon-w3c-module/build/dids'
612
import type {
@@ -48,6 +54,7 @@ import {
4854
injectable,
4955
createPeerDidDocumentFromServices,
5056
PeerDidNumAlgo,
57+
W3cJsonLdVerifiableCredential,
5158
} from '@credo-ts/core'
5259
import { QuestionAnswerRole, QuestionAnswerState } from '@credo-ts/question-answer'
5360
import axios from 'axios'
@@ -68,7 +75,6 @@ import {
6875
WriteTransaction,
6976
CreateProofRequestOobOptions,
7077
CreateOfferOobOptions,
71-
SignDataOptions,
7278
VerifyDataOptions,
7379
} from '../types'
7480

@@ -2157,16 +2163,56 @@ export class MultiTenancyController extends Controller {
21572163
@Post('/sign/:tenantId')
21582164
public async sign(
21592165
@Path('tenantId') tenantId: string,
2160-
@Body() request: SignDataOptions,
2166+
@Body() request: CustomW3cJsonLdSignCredentialOptions | SignDataOptions | any,
2167+
@Res() badRequestError: TsoaResponse<400, { reason: string }>,
21612168
@Res() notFoundError: TsoaResponse<404, { reason: string }>,
21622169
@Res() internalServerError: TsoaResponse<500, { message: string }>
21632170
) {
21642171
try {
21652172
const signature = await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => {
21662173
assertAskarWallet(tenantAgent.context.wallet)
2174+
2175+
// Raw Data Signing
2176+
const rawData = request as SignDataOptions
2177+
2178+
if (!rawData.data) return notFoundError(404, { reason: `Missing "data" for raw data signing` })
2179+
2180+
const hasDidOrMethod = rawData.did || rawData.method
2181+
const hasPublicKey = rawData.publicKeyBase58 && rawData.keyType
2182+
2183+
if (!hasDidOrMethod && !hasPublicKey) {
2184+
return badRequestError(400, {
2185+
reason: `Either (did or method) OR (publicKeyBase58 and keyType) must be provided.`,
2186+
})
2187+
}
2188+
2189+
let keyToUse: Key
2190+
2191+
if (hasDidOrMethod) {
2192+
const dids = await tenantAgent.dids.getCreatedDids({
2193+
method: rawData.method || undefined,
2194+
did: rawData.did || undefined,
2195+
})
2196+
2197+
const verificationMethod = dids[0]?.didDocument?.verificationMethod?.[0]?.publicKeyBase58
2198+
if (!verificationMethod) {
2199+
return badRequestError(400, {
2200+
reason: `No publicKeyBase58 found for the given DID or method.`,
2201+
})
2202+
}
2203+
2204+
keyToUse = Key.fromPublicKeyBase58(verificationMethod, rawData.keyType)
2205+
} else {
2206+
keyToUse = Key.fromPublicKeyBase58(rawData.publicKeyBase58, rawData.keyType)
2207+
}
2208+
2209+
if (!keyToUse) {
2210+
throw new Error('Unable to construct signing key.')
2211+
}
2212+
21672213
const signature = await tenantAgent.context.wallet.sign({
2168-
data: TypedArrayEncoder.fromBase64(request.data),
2169-
key: Key.fromPublicKeyBase58(request.publicKeyBase58, request.keyType),
2214+
data: TypedArrayEncoder.fromBase64(rawData.data),
2215+
key: keyToUse,
21702216
})
21712217
return TypedArrayEncoder.toBase64(signature)
21722218
})
@@ -2194,15 +2240,48 @@ export class MultiTenancyController extends Controller {
21942240
public async verify(
21952241
@Path('tenantId') tenantId: string,
21962242
@Body() request: VerifyDataOptions,
2243+
@Res() badRequestError: TsoaResponse<400, { reason: string }>,
21972244
@Res() notFoundError: TsoaResponse<404, { reason: string }>,
21982245
@Res() internalServerError: TsoaResponse<500, { message: string }>
21992246
) {
22002247
try {
22012248
const isValidSignature = await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => {
22022249
assertAskarWallet(tenantAgent.context.wallet)
2250+
2251+
const hasDidOrMethod = request.did || request.method
2252+
const hasPublicKey = request.publicKeyBase58 && request.keyType
2253+
2254+
if (!hasDidOrMethod && !hasPublicKey) {
2255+
return badRequestError(400, {
2256+
reason: `Either (did or method) OR (publicKeyBase58 and keyType) must be provided.`,
2257+
})
2258+
}
2259+
2260+
let keyToUse: Key
2261+
2262+
if (hasDidOrMethod) {
2263+
const dids = await tenantAgent.dids.getCreatedDids({
2264+
method: request.method || undefined,
2265+
did: request.did || undefined,
2266+
})
2267+
const verificationMethod = dids[0]?.didDocument?.verificationMethod?.[0]?.publicKeyBase58
2268+
if (!verificationMethod) {
2269+
return badRequestError(400, {
2270+
reason: `No publicKeyBase58 found for the given DID or method.`,
2271+
})
2272+
}
2273+
keyToUse = Key.fromPublicKeyBase58(verificationMethod, request.keyType)
2274+
} else {
2275+
keyToUse = Key.fromPublicKeyBase58(request.publicKeyBase58, request.keyType)
2276+
}
2277+
2278+
if (!keyToUse) {
2279+
throw new Error('Unable to construct key.')
2280+
}
2281+
22032282
const isValidSignature = await tenantAgent.context.wallet.verify({
22042283
data: TypedArrayEncoder.fromBase64(request.data),
2205-
key: Key.fromPublicKeyBase58(request.publicKeyBase58, request.keyType),
2284+
key: keyToUse,
22062285
signature: TypedArrayEncoder.fromBase64(request.signature),
22072286
})
22082287
return isValidSignature
@@ -2215,4 +2294,32 @@ export class MultiTenancyController extends Controller {
22152294
return internalServerError(500, { message: `something went wrong: ${error}` })
22162295
}
22172296
}
2297+
2298+
@Security('apiKey')
2299+
@Post('/credential/verify/:tenantId')
2300+
public async verifyCredential(
2301+
@Path('tenantId') tenantId: string,
2302+
@Body() credentialToVerify: SafeW3cJsonLdVerifyCredentialOptions | any,
2303+
@Res() internalServerError: TsoaResponse<500, { message: string }>
2304+
) {
2305+
let formattedCredential
2306+
try {
2307+
await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => {
2308+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2309+
const { credential, ...credentialOptions } = credentialToVerify
2310+
const transformedCredential = JsonTransformer.fromJSON(
2311+
credentialToVerify?.credential,
2312+
W3cJsonLdVerifiableCredential
2313+
)
2314+
const signedCred = await tenantAgent.w3cCredentials.verifyCredential({
2315+
credential: transformedCredential,
2316+
...credentialOptions,
2317+
})
2318+
formattedCredential = signedCred
2319+
})
2320+
return formattedCredential
2321+
} catch (error) {
2322+
return internalServerError(500, { message: `Something went wrong: ${error}` })
2323+
}
2324+
}
22182325
}

src/controllers/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ import type {
2626
Attachment,
2727
KeyType,
2828
JsonLdCredentialFormat,
29+
W3cJsonLdVerifyCredentialOptions,
30+
DataIntegrityProofOptions,
31+
W3cJsonLdSignCredentialOptions,
2932
} from '@credo-ts/core'
33+
import type { LinkedDataProofOptions } from '@credo-ts/core/build/modules/vc/data-integrity/models/LinkedDataProof'
34+
import type { SingleOrArray } from '@credo-ts/core/build/utils'
3035
import type { DIDDocument } from 'did-resolver'
3136

3237
export type TenantConfig = Pick<InitConfig, 'label' | 'connectionImageUrl'> & {
@@ -396,11 +401,24 @@ export type SignDataOptions = {
396401
data: string
397402
keyType: KeyType
398403
publicKeyBase58: string
404+
did?: string
405+
method?: string
399406
}
400407

401408
export type VerifyDataOptions = {
402409
data: string
403410
keyType: KeyType
404411
publicKeyBase58: string
405412
signature: string
413+
did?: string
414+
method?: string
415+
}
416+
417+
export interface SafeW3cJsonLdVerifyCredentialOptions extends W3cJsonLdVerifyCredentialOptions {
418+
// Ommited due to issues with TSOA
419+
proof: SingleOrArray<Omit<LinkedDataProofOptions, 'cryptosuite'> | DataIntegrityProofOptions>
420+
}
421+
422+
export type CustomW3cJsonLdSignCredentialOptions = Omit<W3cJsonLdSignCredentialOptions, 'format'> & {
423+
[key: string]: unknown
406424
}

taskdef/qa-credo-service.json

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"family": "QA_Platform-admin_TASKDEFIITION",
3+
"runtimePlatform": {
4+
"operatingSystemFamily": "LINUX",
5+
"cpuArchitecture": "ARM64"
6+
},
37
"containerDefinitions": [
48
{
59
"name": "Platform-admin",
@@ -8,11 +12,13 @@
812
"memory": 2048,
913
"portMappings": [
1014
{
15+
"name": "platform-admin-8027-tcp",
1116
"containerPort": 8027,
1217
"hostPort": 8027,
1318
"protocol": "tcp"
1419
},
1520
{
21+
"name": "platform-admin-9027-tcp",
1622
"containerPort": 9027,
1723
"hostPort": 9027,
1824
"protocol": "tcp"
@@ -25,7 +31,12 @@
2531
"--config",
2632
"/config/685df587-7cf5-46cf-873c-502719ac5c35_Platform-admin.json"
2733
],
28-
"environment": [],
34+
"environment": [
35+
{
36+
"name": "AFJ_REST_LOG_LEVEL",
37+
"value": "1"
38+
}
39+
],
2940
"environmentFiles": [
3041
{
3142
"value": "arn:aws:s3:::env-qabucket/qa-credo.env",
@@ -50,10 +61,27 @@
5061
"awslogs-stream-prefix": "ecs"
5162
},
5263
"secretOptions": []
53-
}
64+
},
65+
"systemControls": []
5466
}
5567

5668
],
69+
"executionRoleArn": "arn:aws:iam::058264212188:role/ecsTaskExecutionRole",
70+
"networkMode": "awsvpc",
71+
"volumes": [
72+
{
73+
"name": "AGENT-CONFIG",
74+
"efsVolumeConfiguration": {
75+
"fileSystemId": "fs-027dfce09a9626534",
76+
"rootDirectory": "/",
77+
"transitEncryption": "ENABLED",
78+
"authorizationConfig": {
79+
"accessPointId": "fsap-0d962feb103255a71",
80+
"iam": "DISABLED"
81+
}
82+
}
83+
}
84+
],
5785

5886
"executionRoleArn": "arn:aws:iam::id:role/ecsTaskExecutionRole",
5987
"networkMode": "awsvpc",

0 commit comments

Comments
 (0)