diff --git a/qvi-workflow/kli-commands.sh b/qvi-workflow/kli-commands.sh index 3d1d990..6a46d76 100644 --- a/qvi-workflow/kli-commands.sh +++ b/qvi-workflow/kli-commands.sh @@ -15,12 +15,7 @@ fi # Set current working directory for all scripts that must access files KLI1IMAGE="weboftrust/keri:1.1.29" -# KLI1IMAGE="kentbull/keri:1.1.27a" - -# KLI2IMAGE="weboftrust/keri:1.2.0-rc1" KLI2IMAGE="weboftrust/keri:1.2.2" -# KLI2IMAGE="weboftrust/keri:1.1.27" -# KLI2IMAGE="kentbull/keri:1.1.27a" LOCAL_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) export KLI_DATA_DIR="${LOCAL_DIR}/data" diff --git a/qvi-workflow/package-lock.json b/qvi-workflow/package-lock.json index d00e637..2fdc4fb 100644 --- a/qvi-workflow/package-lock.json +++ b/qvi-workflow/package-lock.json @@ -1,11 +1,11 @@ { - "name": "full", + "name": "qvi-workflow", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { - "signify-ts": "git://github.com/WebOfTrust/signify-ts.git#f368351f976ceeefc19082fc8351adbb359c4e77" + "signify-ts": "0.3.0-rc1" }, "devDependencies": { "@types/node": "^22.10.5", @@ -865,9 +865,9 @@ "license": "MIT" }, "node_modules/signify-ts": { - "version": "0.3.0", - "resolved": "git+ssh://git@github.com/WebOfTrust/signify-ts.git#f368351f976ceeefc19082fc8351adbb359c4e77", - "integrity": "sha512-r+NZ92sJaKCTn8Zzw8PXDA/1DikxjxEFF0/+YMuQlWqRcEmJdmdN+u9/oaqnbP8kdWfAn2MENDAav2+RunVcrw==", + "version": "0.3.0-rc1", + "resolved": "https://registry.npmjs.org/signify-ts/-/signify-ts-0.3.0-rc1.tgz", + "integrity": "sha512-mCEt+Dn2l8fzFLePYd+MuBnbht9NhUj3B5NE9NYRhxtFpP+0E/78E8fb6rDwMC9qsRrI9/HX4Jpayt8juR4M2Q==", "license": "Apache-2.0", "workspaces": [ "examples/*" diff --git a/qvi-workflow/package.json b/qvi-workflow/package.json index 4e47dea..3dbc755 100644 --- a/qvi-workflow/package.json +++ b/qvi-workflow/package.json @@ -2,7 +2,7 @@ "type": "module", "private": true, "dependencies": { - "signify-ts": "git://github.com/WebOfTrust/signify-ts.git#f368351f976ceeefc19082fc8351adbb359c4e77" + "signify-ts": "0.3.0-rc1" }, "devDependencies": { "@types/node": "^22.10.5", diff --git a/qvi-workflow/qvi-workflow-keria_signify_qvi.sh b/qvi-workflow/qvi-workflow-keria_signify_qvi.sh index a22fd2e..3f7b5ca 100755 --- a/qvi-workflow/qvi-workflow-keria_signify_qvi.sh +++ b/qvi-workflow/qvi-workflow-keria_signify_qvi.sh @@ -161,10 +161,10 @@ test_dependencies # KERIA SignifyTS QVI salts SIGTS_AIDS="qar1|$QAR_PT1|$QAR_PT1_SALT,qar2|$QAR_PT2|$QAR_PT2_SALT,qar3|$QAR_PT3|$QAR_PT3_SALT,person|$PERSON|$PERSON_SALT" -tsx "${QVI_SIGNIFY_DIR}/qars-and-person-setup.ts" $ENVIRONMENT $QVI_DATA_DIR $SIGTS_AIDS -echo "QVI and Person Identifiers from SignifyTS + KERIA are " +tsx "${QVI_SIGNIFY_DIR}/qars/qars-and-person-setup.ts" $ENVIRONMENT $QVI_DATA_DIR $SIGTS_AIDS +#echo "QVI and Person Identifiers from SignifyTS + KERIA are " qvi_setup_data=$(cat "${QVI_DATA_DIR}"/qars-and-person-info.json) -echo $qvi_setup_data | jq +#echo $qvi_setup_data | jq QAR_PT1_PRE=$(echo $qvi_setup_data | jq -r ".QAR1.aid" | tr -d '"') QAR_PT2_PRE=$(echo $qvi_setup_data | jq -r ".QAR2.aid" | tr -d '"') QAR_PT3_PRE=$(echo $qvi_setup_data | jq -r ".QAR3.aid" | tr -d '"') @@ -188,8 +188,6 @@ function create_temp_icp_cfg() { "nsith": "1" } EOM - print_lcyan "Using temporary AID config file heredoc:" - print_lcyan "${ICP_CONFIG_JSON}" # create temporary file to store json temp_icp_config=$(mktemp) @@ -252,7 +250,11 @@ function resolve_credential_oobis() { # 2. GAR: Create single Sig AIDs (2) function create_aids() { print_green "-----Creating AIDs-----" + create_temp_icp_cfg + print_lcyan "Using temporary AID config file heredoc:" + print_lcyan "${temp_icp_config}" + create_aid "${GEDA_PT1}" "${GEDA_PT1_SALT}" "${GEDA_PT1_PASSCODE}" "${CONFIG_DIR}" "${INIT_CFG}" "${temp_icp_config}" create_aid "${GEDA_PT2}" "${GEDA_PT2_SALT}" "${GEDA_PT2_PASSCODE}" "${CONFIG_DIR}" "${INIT_CFG}" "${temp_icp_config}" create_aid "${GIDA_PT1}" "${GIDA_PT1_SALT}" "${GIDA_PT1_PASSCODE}" "${CONFIG_DIR}" "${INIT_CFG}" "${temp_icp_config}" @@ -278,7 +280,7 @@ function resolve_oobis() { OOBIS_FOR_KERIA="geda1|$GEDA1_OOBI,geda2|$GEDA2_OOBI,gida1|$GIDA1_OOBI,gida2|$GIDA2_OOBI,sally|$SALLY_OOBI" - tsx "${QVI_SIGNIFY_DIR}/qars-person-single-sig-oobis-setup.ts" $ENVIRONMENT $SIGTS_AIDS $OOBIS_FOR_KERIA + tsx "${QVI_SIGNIFY_DIR}/qars/qars-person-single-sig-oobis-setup.ts" $ENVIRONMENT $SIGTS_AIDS $OOBIS_FOR_KERIA echo print_lcyan "-----Resolving OOBIs-----" @@ -325,7 +327,7 @@ resolve_oobis # 3.5 GAR: Challenge responses between single sig AIDs function challenge_response() { chall_length=$(kli contacts list --name "${GEDA_PT1}" --passcode "${GEDA_PT1_PASSCODE}" | jq "select(.alias == \"${GEDA_PT2}\") | .challenges | length") - if [[ "$chall_length" > 0 ]]; then + if [[ "$chall_length" -gt 0 ]]; then print_yellow "Challenges already processed" return fi @@ -346,6 +348,7 @@ function challenge_response() { print_dark_gray "---Challenge responses for QAR---" + # TODO add qars-challenge-each-other.ts print_dark_gray "Challenge: QAR 1 -> QAR 2" words_qar1_to_qar2=$(kli challenge generate --out string) kli challenge respond --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --recipient "${QAR_PT1}" --words "${words_qar1_to_qar2}" @@ -357,26 +360,30 @@ function challenge_response() { kli challenge verify --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --signer "${QAR_PT1}" --words "${words_qar2_to_qar1}" print_dark_gray "---Challenge responses between GEDA and QAR---" - + print_dark_gray "Challenge: GEDA 1 -> QAR 1" words_geda1_to_qar1=$(kli challenge generate --out string) - kli challenge respond --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --recipient "${GEDA_PT1}" --words "${words_geda1_to_qar1}" + # TODO add qars-challenge-respond.ts + # kli challenge respond --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --recipient "${GEDA_PT1}" --words "${words_geda1_to_qar1}" kli challenge verify --name "${GEDA_PT1}" --alias "${GEDA_PT1}" --passcode "${GEDA_PT1_PASSCODE}" --signer "${QAR_PT1}" --words "${words_geda1_to_qar1}" print_dark_gray "Challenge: QAR 1 -> GEDA 1" words_qar1_to_geda1=$(kli challenge generate --out string) kli challenge respond --name "${GEDA_PT1}" --alias "${GEDA_PT1}" --passcode "${GEDA_PT1_PASSCODE}" --recipient "${QAR_PT1}" --words "${words_qar1_to_geda1}" - kli challenge verify --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --signer "${GEDA_PT1}" --words "${words_qar1_to_geda1}" + # TODO add qars-challenge-verify.ts + # kli challenge verify --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --signer "${GEDA_PT1}" --words "${words_qar1_to_geda1}" print_dark_gray "Challenge: GEDA 2 -> QAR 2" words_geda1_to_qar2=$(kli challenge generate --out string) - kli challenge respond --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --recipient "${GEDA_PT1}" --words "${words_geda1_to_qar2}" + # TODO add qars-challenge-respond.ts + # kli challenge respond --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --recipient "${GEDA_PT1}" --words "${words_geda1_to_qar2}" kli challenge verify --name "${GEDA_PT1}" --alias "${GEDA_PT1}" --passcode "${GEDA_PT1_PASSCODE}" --signer "${QAR_PT2}" --words "${words_geda1_to_qar2}" print_dark_gray "Challenge: QAR 2 -> GEDA 1" words_qar2_to_geda1=$(kli challenge generate --out string) kli challenge respond --name "${GEDA_PT1}" --alias "${GEDA_PT1}" --passcode "${GEDA_PT1_PASSCODE}" --recipient "${QAR_PT2}" --words "${words_qar2_to_geda1}" - kli challenge verify --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --signer "${GEDA_PT1}" --words "${words_qar2_to_geda1}" + # TODO add qars-challenge-verify.ts + # kli challenge verify --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --signer "${GEDA_PT1}" --words "${words_qar2_to_geda1}" print_dark_gray "---Challenge responses for GIDA (LE)---" @@ -395,26 +402,31 @@ function challenge_response() { print_dark_gray "Challenge: QAR 1 -> GIDA 1" words_qar1_to_gida1=$(kli challenge generate --out string) kli challenge respond --name "${GIDA_PT1}" --alias "${GIDA_PT1}" --passcode "${GIDA_PT1_PASSCODE}" --recipient "${QAR_PT1}" --words "${words_qar1_to_gida1}" - kli challenge verify --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --signer "${GIDA_PT1}" --words "${words_qar1_to_gida1}" + # TODO add qars-challenge-verify.ts + # kli challenge verify --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --signer "${GIDA_PT1}" --words "${words_qar1_to_gida1}" print_dark_gray "Challenge: GIDA 1 -> QAR 1" words_gida1_to_qar1=$(kli challenge generate --out string) - kli challenge respond --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --recipient "${GIDA_PT1}" --words "${words_gida1_to_qar1}" + # TODO add qars-challenge-respond.ts + # kli challenge respond --name "${QAR_PT1}" --alias "${QAR_PT1}" --passcode "${QAR_PT1_PASSCODE}" --recipient "${GIDA_PT1}" --words "${words_gida1_to_qar1}" kli challenge verify --name "${GIDA_PT1}" --alias "${GIDA_PT1}" --passcode "${GIDA_PT1_PASSCODE}" --signer "${QAR_PT1}" --words "${words_gida1_to_qar1}" print_dark_gray "Challenge: QAR 2 -> GIDA 2" words_qar2_to_gida2=$(kli challenge generate --out string) kli challenge respond --name "${GIDA_PT2}" --alias "${GIDA_PT2}" --passcode "${GIDA_PT2_PASSCODE}" --recipient "${QAR_PT2}" --words "${words_qar2_to_gida2}" - kli challenge verify --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --signer "${GIDA_PT2}" --words "${words_qar2_to_gida2}" + # TODO add qars-challenge-verify.ts + # kli challenge verify --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --signer "${GIDA_PT2}" --words "${words_qar2_to_gida2}" print_dark_gray "Challenge: GIDA 2 -> QAR 2" words_gida2_to_qar2=$(kli challenge generate --out string) - kli challenge respond --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --recipient "${GIDA_PT2}" --words "${words_gida2_to_qar2}" + # TODO add qars-challenge-respond.ts + # kli challenge respond --name "${QAR_PT2}" --alias "${QAR_PT2}" --passcode "${QAR_PT2_PASSCODE}" --recipient "${GIDA_PT2}" --words "${words_gida2_to_qar2}" kli challenge verify --name "${GIDA_PT2}" --alias "${GIDA_PT2}" --passcode "${GIDA_PT2_PASSCODE}" --signer "${QAR_PT2}" --words "${words_gida2_to_qar2}" print_green "-----Finished challenge and response-----" } -# challenge_response +# TODO enable this after challenge response with SignifyTS is integrated +#challenge_response # 4. GAR: Create Multisig AID (GEDA) function create_geda_multisig() { @@ -584,7 +596,7 @@ function resolve_geda_and_gida_oobis() { MULTISIG_OOBIS="gedaMS|$GEDA_OOBI,gidaMS|$GIDA_OOBI" echo "GEDA OOBI: ${GEDA_OOBI}" echo "GIDA OOBI: ${GIDA_OOBI}" - tsx "${QVI_SIGNIFY_DIR}/qars-resolve-geda-and-le-oobis.ts" $ENVIRONMENT $SIGTS_AIDS $MULTISIG_OOBIS + tsx "${QVI_SIGNIFY_DIR}/qars/qars-resolve-geda-and-le-oobis.ts" $ENVIRONMENT $SIGTS_AIDS $MULTISIG_OOBIS } resolve_geda_and_gida_oobis @@ -592,7 +604,11 @@ resolve_geda_and_gida_oobis # 11. QVI: Create delegated AID with GEDA as delegator # 12. GEDA: delegate to QVI function create_qvi_multisig() { - QVI_MULTISIG_EXISTS=$(tsx "${QVI_SIGNIFY_DIR}/qar-check-qvi-multisig.ts" $ENVIRONMENT $SIGTS_AIDS) + QVI_MULTISIG_EXISTS=$(tsx "${QVI_SIGNIFY_DIR}/qars/qar-check-qvi-multisig.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${SIGTS_AIDS}" + ) if [[ "$QVI_MULTISIG_EXISTS" == "true" ]]; then print_dark_gray "[QVI] Multisig AID ${QVI_MS} already exists" return @@ -600,7 +616,12 @@ function create_qvi_multisig() { print_yellow "Creating QVI multisig" local delegator_prefix=$(kli status --name ${GEDA_PT1} --alias ${GEDA_MS} --passcode ${GEDA_PT1_PASSCODE} | awk '/Identifier:/ {print $2}') - tsx "${QVI_SIGNIFY_DIR}/qars-create-qvi-multisig.ts" $ENVIRONMENT $QVI_DATA_DIR $SIGTS_AIDS $delegator_prefix + tsx "${QVI_SIGNIFY_DIR}/qars/qars-create-qvi-multisig.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${QVI_DATA_DIR}" \ + "${SIGTS_AIDS}" \ + "${delegator_prefix}" local delegated_multisig_info=$(cat $QVI_DATA_DIR/qvi-multisig-info.json) print_yellow "Delegated Multisig Info:" print_lcyan $delegated_multisig_info @@ -624,7 +645,7 @@ function create_qvi_multisig() { wait $PID_LIST print_lcyan "[QVI] QARs refresh GEDA multisig keystate to discover new GEDA delegation seal anchored in interaction event." - tsx "${QVI_SIGNIFY_DIR}/qars-refresh-geda-multisig-state.ts" $ENVIRONMENT $SIGTS_AIDS $GEDA_PRE + tsx "${QVI_SIGNIFY_DIR}/qars/qars-refresh-geda-multisig-state.ts" $ENVIRONMENT $SIGTS_AIDS $GEDA_PRE } create_qvi_multisig MULTISIG_INFO=$(cat $QVI_DATA_DIR/qvi-multisig-info.json) @@ -636,7 +657,11 @@ print_green "[QVI] Multisig AID ${QVI_MS} with prefix: ${QVI_PRE}" QVI_OOBI="" function authorize_qvi_multisig_agent_endpoint_role(){ print_yellow "Authorizing QVI multisig agent endpoint role" - tsx "${QVI_SIGNIFY_DIR}/qars-authorize-endroles-get-qvi-oobi.ts" $ENVIRONMENT $QVI_DATA_DIR $SIGTS_AIDS + tsx "${QVI_SIGNIFY_DIR}/qars/qars-authorize-endroles-get-qvi-oobi.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${QVI_DATA_DIR}" \ + "${SIGTS_AIDS}" QVI_OOBI=$(cat "${QVI_DATA_DIR}/qvi-oobi.json" | jq .oobi | tr -d '"') } authorize_qvi_multisig_agent_endpoint_role @@ -660,7 +685,11 @@ function resolve_qvi_oobi() { kli oobi resolve --name "${GIDA_PT2}" --oobi-alias "${QVI_MS}" --passcode "${GIDA_PT2_PASSCODE}" --oobi "${QVI_OOBI}" print_yellow "Resolving QVI OOBI for Person" - tsx "${QVI_SIGNIFY_DIR}/person-resolve-qvi-oobi.ts" $ENVIRONMENT $SIGTS_AIDS $QVI_OOBI + tsx "${QVI_SIGNIFY_DIR}/person-resolve-qvi-oobi.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${SIGTS_AIDS}" \ + "${QVI_OOBI}" echo } resolve_qvi_oobi @@ -718,9 +747,6 @@ function prepare_qvi_cred_data() { EOM echo "$QVI_CRED_DATA" > ./qvi-cred-data.json - - print_lcyan "QVI Credential Data" - print_lcyan "$(cat ./qvi-cred-data.json)" } prepare_qvi_cred_data @@ -740,31 +766,34 @@ function create_qvi_credential() { echo print_green "[External] GEDA creating QVI credential" - KLI_TIME=$(kli time) + print_lcyan "[External] QVI Credential Data" + print_lcyan "$(cat ./qvi-cred-data.json)" + + KLI_TIME=$(kli time) # use consistent time for both invocations of `kli vc create` so they compute the same event digest (SAID). PID_LIST="" kli vc create \ - --name ${GEDA_PT1} \ - --alias ${GEDA_MS} \ - --passcode ${GEDA_PT1_PASSCODE} \ - --registry-name ${GEDA_REGISTRY} \ + --name "${GEDA_PT1}" \ + --alias "${GEDA_MS}" \ + --passcode "${GEDA_PT1_PASSCODE}" \ + --registry-name "${GEDA_REGISTRY}" \ --schema "${QVI_SCHEMA}" \ - --recipient ${QVI_PRE} \ + --recipient "${QVI_PRE}" \ --data @./qvi-cred-data.json \ --rules @./rules.json \ - --time ${KLI_TIME} & + --time "${KLI_TIME}" & pid=$! PID_LIST+=" $pid" kli vc create \ - --name ${GEDA_PT2} \ - --alias ${GEDA_MS} \ - --passcode ${GEDA_PT2_PASSCODE} \ - --registry-name ${GEDA_REGISTRY} \ + --name "${GEDA_PT2}" \ + --alias "${GEDA_MS}" \ + --passcode "${GEDA_PT2_PASSCODE}" \ + --registry-name "${GEDA_REGISTRY}" \ --schema "${QVI_SCHEMA}" \ - --recipient ${QVI_PRE} \ + --recipient "${QVI_PRE}" \ --data @./qvi-cred-data.json \ --rules @./rules.json \ - --time ${KLI_TIME} & + --time "${KLI_TIME}" & pid=$! PID_LIST+=" $pid" @@ -837,15 +866,25 @@ function admit_qvi_credential() { --issued \ --said \ --schema "${QVI_SCHEMA}") - received=$(tsx "${QVI_SIGNIFY_DIR}/qar-check-qvi-credential.ts" $ENVIRONMENT $SIGTS_AIDS $QVI_CRED_SAID) + received=$(tsx "${QVI_SIGNIFY_DIR}/qars/qar-check-received-credential.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${SIGTS_AIDS}" \ + "${QVI_CRED_SAID}" + ) if [[ "$received" == "true" ]]; then - print_dark_gray "[QVI] QVI Credential already admitted" + print_dark_gray "[QVI] QVI Credential ${QVI_CRED_SAID} already admitted" return fi echo - print_yellow "[QVI] Admitting QVI Credential ${SAID} from GEDA" - tsx "${QVI_SIGNIFY_DIR}/qars-admit-qvi-credential.ts" $ENVIRONMENT $SIGTS_AIDS $GEDA_PRE $QVI_CRED_SAID + print_yellow "[QVI] Admitting QVI Credential ${QVI_CRED_SAID} from GEDA" + tsx "${QVI_SIGNIFY_DIR}/qars/qars-admit-qvi-credential.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${SIGTS_AIDS}" \ + "${GEDA_PRE}" \ + "${QVI_CRED_SAID}" echo print_green "[QVI] Admitted QVI credential" @@ -853,9 +892,30 @@ function admit_qvi_credential() { } admit_qvi_credential +# 18.1 QVI: Delegated multisig rotation() { +function qvi_rotate() { + print_yellow "[QVI] Rotating QVI Multisig" + tsx "${QVI_SIGNIFY_DIR}/qars/qars-rotate-qvi-multisig.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${QVI_DATA_DIR}" \ + "${SIGTS_AIDS}" + QVI_ROTATE_PREFIX=$(cat "${QVI_DATA_DIR}/qvi-multisig-info.json" | jq .msPrefix | tr -d '"') + print_green "[QVI] Rotated QVI Multisig with prefix: ${QVI_ROTATE_PREFIX}" + + +} +qvi_rotate +cleanup + # 18.5 Create QVI credential registry function create_qvi_reg() { - tsx "${QVI_SIGNIFY_DIR}/qars-registry-create.ts" $ENVIRONMENT $QVI_DATA_DIR $SIGTS_AIDS + tsx "${QVI_SIGNIFY_DIR}/qars/qars-registry-create.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "${QVI_REGISTRY}" \ + "${QVI_DATA_DIR}" \ + "${SIGTS_AIDS}" QVI_REG_REGK=$(cat "${QVI_DATA_DIR}/qvi-registry-info.json" | jq .registryRegk | tr -d '"') print_green "[QVI] Credential Registry created for QVI with regk: ${QVI_REG_REGK}" } @@ -887,53 +947,8 @@ EOM echo "$QVI_EDGE_JSON" > ./qvi-edge.json kli saidify --file ./qvi-edge.json - - print_lcyan "Legal Entity edge Data" - print_lcyan "$(cat ./qvi-edge.json | jq )" } -prepare_qvi_edge - -# 19.1.5 GIDA: Create GIDA credential registry -function create_gida_reg() { - # Check if GIDA credential registry already exists - REGISTRY=$(kli vc registry list \ - --name "${GIDA_PT1}" \ - --passcode "${GIDA_PT1_PASSCODE}" | awk '{print $1}') - if [ ! -z "${REGISTRY}" ]; then - print_dark_gray "[Internal] GIDA registry already created" - return - fi - - echo - print_yellow "[Internal] Creating GIDA registry" - NONCE=$(kli nonce) - PID_LIST="" - kli vc registry incept \ - --name ${GIDA_PT1} \ - --alias ${GIDA_MS} \ - --passcode ${GIDA_PT1_PASSCODE} \ - --usage "Legal Entity Credential Registry for GIDA (LE)" \ - --nonce ${NONCE} \ - --registry-name ${GIDA_REGISTRY} & - pid=$! - PID_LIST+=" $pid" - - kli vc registry incept \ - --name ${GIDA_PT2} \ - --alias ${GIDA_MS} \ - --passcode ${GIDA_PT2_PASSCODE} \ - --usage "Legal Entity Credential Registry for GIDA (LE)" \ - --nonce ${NONCE} \ - --registry-name ${GIDA_REGISTRY} & - pid=$! - PID_LIST+=" $pid" - wait $PID_LIST - - echo - print_green "[Internal] Legal Entity Credential Registry created for GIDA" - echo -} -create_gida_reg +prepare_qvi_edge # 19.2 Prepare LE credential data function prepare_le_cred_data() { @@ -945,16 +960,19 @@ function prepare_le_cred_data() { EOM echo "$LE_CRED_DATA" > ./legal-entity-data.json - - print_lcyan "[QVI] Legal Entity Credential Data" - print_lcyan "$(cat ./legal-entity-data.json)" } prepare_le_cred_data # 19.3 Create LE credential in QVI function create_and_grant_le_credential() { # Check if LE credential already exists - received=$(tsx "${QVI_SIGNIFY_DIR}/qar-check-le-credential.ts" $ENVIRONMENT $SIGTS_AIDS $QVI_CRED_SAID) + received=$(tsx "${QVI_SIGNIFY_DIR}/qars/qar-check-issued-credential.ts" \ + $ENVIRONMENT \ + $QVI_MS \ + $SIGTS_AIDS \ + $GIDA_PRE \ + $LE_SCHEMA + ) if [[ "$received" == "true" ]]; then print_dark_gray "[QVI] LE Credential already created" return @@ -963,18 +981,29 @@ function create_and_grant_le_credential() { echo print_green "[QVI] creating LE credential" - tsx "${QVI_SIGNIFY_DIR}/qars-le-credential-create.ts" $ENVIRONMENT "./" $SIGTS_AIDS $GIDA_PRE $QVI_SAID + print_lcyan "[QVI] Legal Entity edge Data" + print_lcyan "$(cat ./qvi-edge.json | jq )" + + print_lcyan "[QVI] Legal Entity Credential Data" + print_lcyan "$(cat ./legal-entity-data.json)" + + tsx "${QVI_SIGNIFY_DIR}/qars/qars-le-credential-create.ts" \ + "${ENVIRONMENT}" \ + "${QVI_MS}" \ + "./" \ + "${SIGTS_AIDS}" \ + "${GIDA_PRE}" \ + "${QVI_SAID}" echo print_lcyan "[QVI] LE Credential created" + print_dark_gray "Waiting 10 seconds for LE credential to be witnessed..." + sleep 10 echo } create_and_grant_le_credential -print_dark_gray "Waiting 10 seconds for LE credential to be witnessed..." -sleep 10 - -# 20. GEDA: Admit LE credential from QVI +# 19.4. GIDA (LE): Admit LE credential from QVI function admit_le_credential() { VC_SAID=$(kli vc list \ --name "${GIDA_PT2}" \ @@ -1034,18 +1063,59 @@ function admit_le_credential() { echo } admit_le_credential -cleanup -# 21. GEDA: Prepare, create, and Issue ECR Auth & OOR Auth credential to QVI +# 20. GIDA (LE): Create GIDA credential registry +function create_gida_reg() { + # Check if GIDA credential registry already exists + REGISTRY=$(kli vc registry list \ + --name "${GIDA_PT1}" \ + --passcode "${GIDA_PT1_PASSCODE}" | awk '{print $1}') + if [ ! -z "${REGISTRY}" ]; then + print_dark_gray "[Internal] GIDA registry already created" + return + fi + + echo + print_yellow "[Internal] Creating GIDA registry" + NONCE=$(kli nonce) + PID_LIST="" + kli vc registry incept \ + --name "${GIDA_PT1}" \ + --alias "${GIDA_MS}" \ + --passcode "${GIDA_PT1_PASSCODE}" \ + --usage "Legal Entity Credential Registry for GIDA (LE)" \ + --nonce "${NONCE}" \ + --registry-name "${GIDA_REGISTRY}" & + pid=$! + PID_LIST+=" $pid" + + kli vc registry incept \ + --name "${GIDA_PT2}" \ + --alias "${GIDA_MS}" \ + --passcode "${GIDA_PT2_PASSCODE}" \ + --usage "Legal Entity Credential Registry for GIDA (LE)" \ + --nonce "${NONCE}" \ + --registry-name "${GIDA_REGISTRY}" & + pid=$! + PID_LIST+=" $pid" + wait $PID_LIST + + echo + print_green "[Internal] Legal Entity Credential Registry created for GIDA" + echo +} +create_gida_reg + +# 21. GIDA (LE): Prepare, create, and Issue ECR Auth & OOR Auth credential to QVI # 21.1 prepare LE edge to ECR auth cred function prepare_le_edge() { LE_SAID=$(kli vc list \ - --name ${GIDA_PT1} \ - --alias ${GIDA_MS} \ + --name "${GIDA_PT1}" \ + --alias "${GIDA_MS}" \ --passcode "${GIDA_PT1_PASSCODE}" \ --said \ - --schema ${LE_SCHEMA}) + --schema "${LE_SCHEMA}") print_bg_blue "[Internal] Preparing ECR Auth cred with LE Credential SAID: ${LE_SAID}" read -r -d '' LE_EDGE_JSON << EOM { @@ -1059,9 +1129,6 @@ EOM echo "$LE_EDGE_JSON" > ./legal-entity-edge.json kli saidify --file ./legal-entity-edge.json - - print_lcyan "[Internal] Legal Entity edge JSON" - print_lcyan "$(cat ./legal-entity-edge.json | jq)" } prepare_le_edge @@ -1077,8 +1144,6 @@ function prepare_ecr_auth_data() { EOM echo "$ECR_AUTH_DATA_JSON" > ./ecr-auth-data.json - print_lcyan "[Internal] ECR Auth data JSON" - print_lcyan "$(cat ./ecr-auth-data.json)" } prepare_ecr_auth_data @@ -1100,34 +1165,40 @@ function create_ecr_auth_credential() { echo print_green "[Internal] GIDA creating ECR Auth credential" + print_lcyan "[Internal] Legal Entity edge JSON" + print_lcyan "$(cat ./legal-entity-edge.json | jq)" + + print_lcyan "[Internal] ECR Auth data JSON" + print_lcyan "$(cat ./ecr-auth-data.json)" + KLI_TIME=$(kli time) PID_LIST="" kli vc create \ - --name ${GIDA_PT1} \ - --alias ${GIDA_MS} \ - --passcode ${GIDA_PT1_PASSCODE} \ - --registry-name ${GIDA_REGISTRY} \ - --schema ${ECR_AUTH_SCHEMA} \ - --recipient ${QVI_PRE} \ + --name "${GIDA_PT1}" \ + --alias "${GIDA_MS}" \ + --passcode "${GIDA_PT1_PASSCODE}" \ + --registry-name "${GIDA_REGISTRY}" \ + --schema "${ECR_AUTH_SCHEMA}" \ + --recipient "${QVI_PRE}" \ --data @./ecr-auth-data.json \ --edges @./legal-entity-edge.json \ --rules @./ecr-auth-rules.json \ - --time ${KLI_TIME} & + --time "${KLI_TIME}" & pid=$! PID_LIST+=" $pid" kli vc create \ - --name ${GIDA_PT2} \ - --alias ${GIDA_MS} \ - --passcode ${GIDA_PT2_PASSCODE} \ - --registry-name ${GIDA_REGISTRY} \ - --schema ${ECR_AUTH_SCHEMA} \ - --recipient ${QVI_PRE} \ + --name "${GIDA_PT2}" \ + --alias "${GIDA_MS}" \ + --passcode "${GIDA_PT2_PASSCODE}" \ + --registry-name "${GIDA_REGISTRY}" \ + --schema "${ECR_AUTH_SCHEMA}" \ + --recipient "${QVI_PRE}" \ --data @./ecr-auth-data.json \ --edges @./legal-entity-edge.json \ --rules @./ecr-auth-rules.json \ - --time ${KLI_TIME} & + --time "${KLI_TIME}" & pid=$! PID_LIST+=" $pid" @@ -1143,14 +1214,14 @@ create_ecr_auth_credential function grant_ecr_auth_credential() { # This relies on there being only one grant in the list for the GEDA GRANT_COUNT=$(kli ipex list \ - --name "${QAR_PT1}" \ - --alias "${QVI_MS}" \ + --name "${GIDA_PT1}" \ + --alias "${GIDA_MS}" \ --type "grant" \ - --passcode "${QAR_PT1_PASSCODE}" \ - --poll \ + --passcode "${GIDA_PT1_PASSCODE}" \ + --sent \ --said | wc -l | tr -d ' ') # get the last grant - if [ "${GRANT_COUNT}" -ge 2 ]; then - print_dark_gray "[QVI] ECR Auth credential grant already received" + if [ "${GRANT_COUNT}" -ge 1 ]; then + print_dark_gray "[GIDA] ECR Auth credential grant already granted" return fi SAID=$(kli vc list \ @@ -1166,18 +1237,18 @@ function grant_ecr_auth_credential() { KLI_TIME=$(kli time) # Use consistent time so SAID of grant is same kli ipex grant \ - --name ${GIDA_PT1} \ - --passcode ${GIDA_PT1_PASSCODE} \ - --alias ${GIDA_MS} \ - --said ${SAID} \ - --recipient ${QVI_PRE} \ - --time ${KLI_TIME} & + --name "${GIDA_PT1}" \ + --passcode "${GIDA_PT1_PASSCODE}" \ + --alias "${GIDA_MS}" \ + --said "${SAID}" \ + --recipient "${QVI_PRE}" \ + --time "${KLI_TIME}" & pid=$! PID_LIST+=" $pid" kli ipex join \ - --name ${GIDA_PT2} \ - --passcode ${GIDA_PT2_PASSCODE} \ + --name "${GIDA_PT2}" \ + --passcode "${GIDA_PT2_PASSCODE}" \ --auto & pid=$! PID_LIST+=" $pid" @@ -1188,43 +1259,38 @@ function grant_ecr_auth_credential() { print_yellow "[Internal] Waiting for IPEX messages to be witnessed" sleep 5 - echo - print_green "[QVI] Polling for ECR Auth Credential in ${QAR_PT1}..." - kli ipex list \ - --name "${QAR_PT1}" \ - --alias "${QVI_MS}" \ - --passcode "${QAR_PT1_PASSCODE}" \ - --type "grant" \ - --poll \ - --said - - print_green "[QVI] Polling for ECR Auth Credential in ${QAR_PT2}..." - kli ipex list \ - --name "${QAR_PT2}" \ - --alias "${QVI_MS}" \ - --passcode "${QAR_PT2_PASSCODE}" \ - --type "grant" \ - --poll \ - --said - echo print_green "[Internal] ECR Auth Credential granted to QVI" echo } grant_ecr_auth_credential +cleanup + +# TODO use SignifyTS for the following steps: +# - ECR Auth admit, +# - OOR Auth admit, +# - ECR/OOR create, +# - ECR/OOR grant, +# - ECR/OOR admit, +# - ECR/OOR present to Sally, verify webhook called # 21.5 (part of 22) Admit ECR Auth credential from GIDA function admit_ecr_auth_credential() { VC_SAID=$(kli vc list \ - --name "${QAR_PT2}" \ - --alias "${QVI_MS}" \ - --passcode "${QAR_PT2_PASSCODE}" \ + --name "${GIDA_PT2}" \ + --alias "${GIDA_MS}" \ + --passcode "${GIDA_PT2_PASSCODE}" \ + --issued \ --said \ --schema ${ECR_AUTH_SCHEMA}) + received=$(tsx "${QVI_SIGNIFY_DIR}/qars/qar-check-credential.ts" "$ENVIRONMENT" "$SIGTS_AIDS" "${QVI_CRED_SAID}") if [ ! -z "${VC_SAID}" ]; then - print_dark_gray "[QVI] ECR Auth Credential already admitted" + print_dark_gray "[GIDA] ECR Auth Credential already admitted" return fi + print_red "Early exit" + cleanup + SAID=$(kli ipex list \ --name "${QAR_PT1}" \ --alias "${QVI_MS}" \ @@ -1262,6 +1328,8 @@ function admit_ecr_auth_credential() { echo } admit_ecr_auth_credential +print_red "Early exit" + cleanup # 21.6 Prepare OOR Auth credential data function prepare_oor_auth_data() { diff --git a/qvi-workflow/qvi-workflow-kli.sh b/qvi-workflow/qvi-workflow-kli.sh index 4d936c3..3d0980a 100755 --- a/qvi-workflow/qvi-workflow-kli.sh +++ b/qvi-workflow/qvi-workflow-kli.sh @@ -123,6 +123,28 @@ OOR_AUTH_SCHEMA=EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E ECR_SCHEMA=EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw OOR_SCHEMA=EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy +function test_dependencies() { + # check that sally is installed and available on the PATH + command -v kli >/dev/null 2>&1 || { print_red "kli is not installed or not available on the PATH. Aborting."; exit 1; } + command -v tsx >/dev/null 2>&1 || { print_red "tsx is not installed or not available on the PATH. Aborting."; exit 1; } + command -v jq >/dev/null 2>&1 || { print_red "jq is not installed or not available on the PATH. Aborting."; exit 1; } + command -v sally >/dev/null 2>&1 || { print_red "sally is not installed or not available on the PATH. Aborting."; exit 1; } + + curl ${WIT_HOST}/oobi/${WAN_PRE} >/dev/null 2>&1 + status=$? + if [ $status -ne 0 ]; then + print_red "Witness server not running at ${WIT_HOST}" + cleanup + fi + + curl ${SCHEMA_SERVER}/oobi/${QVI_SCHEMA} >/dev/null 2>&1 + status=$? + if [ $status -ne 0 ]; then + print_red "Schema server not running at ${SCHEMA_SERVER}" + cleanup + fi +} +test_dependencies # functions temp_icp_config="" function create_temp_icp_cfg() { diff --git a/qvi-workflow/signify_qvi/person-resolve-qvi-oobi.ts b/qvi-workflow/signify_qvi/person-resolve-qvi-oobi.ts index 5b01dc1..f1f91f4 100644 --- a/qvi-workflow/signify_qvi/person-resolve-qvi-oobi.ts +++ b/qvi-workflow/signify_qvi/person-resolve-qvi-oobi.ts @@ -7,10 +7,9 @@ import { OobiInfo } from "./qvi-data"; // Pull in arguments from the command line and configuration const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const aidInfoArg = args[1]; -const qviOobiArg = args[2]; - -const QVI_MS_NAME='QVI'; +const multisigName = args[1]; +const aidInfoArg = args[2]; +const qviOobiArg = args[3]; // parse the OOBIs for the GEDA and GIDA multisig AIDs needed for delegation and then LE credential issuance export function parseOobiInfo(oobiInfo: string) { @@ -31,11 +30,11 @@ export function parseOobiInfo(oobiInfo: string) { * @param qviOobi The QVI multisig OOBI * @param environment the runtime environment to use for resolving environment variables */ -async function resolveQVIOobi(aidInfo: string, qviOobi: string, environment: TestEnvironmentPreset) { +async function resolveQVIOobi(multisigName: string, aidInfo: string, qviOobi: string, environment: TestEnvironmentPreset) { // create SignifyTS Clients const {PERSON} = parseAidInfo(aidInfo); const [PERSONClient] = await getOrCreateClients(1, [PERSON.salt], environment); - await getOrCreateContact(PERSONClient, QVI_MS_NAME, qviOobi); + await getOrCreateContact(PERSONClient, multisigName, qviOobi); } -await resolveQVIOobi(aidInfoArg, qviOobiArg, env); +await resolveQVIOobi(multisigName, aidInfoArg, qviOobiArg, env); console.log('Person resolved QVI OOBI ' + qviOobiArg); \ No newline at end of file diff --git a/qvi-workflow/signify_qvi/qar-check-le-credential.ts b/qvi-workflow/signify_qvi/qar-check-le-credential.ts deleted file mode 100644 index 560f78e..0000000 --- a/qvi-workflow/signify_qvi/qar-check-le-credential.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { HabState } from "signify-ts"; -import { parseAidInfo } from "./create-aid"; -import { getOrCreateClients } from "./keystore-creation"; -import { TestEnvironmentPreset } from "./resolve-env"; -import { getIssuedCredential } from "./credentials"; - -// process arguments -const args = process.argv.slice(2); -const env = args[0] as 'local' | 'docker'; -const aidInfoArg = args[1] -const lePrefix = args[2] - -const QVI_MS_NAME='QVI'; -const LE_SCHEMA_SAID = 'ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY'; - - -/** - * Checks to see if the QVI credential exists for the QAR - * - * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position - * @param lePrefix identifier prefix for the Legal Entity multisig AID who would be the recipient, or issuee, of the LE credential. - * @param environment the runtime environment to use for resolving environment variables - * @returns {Promise} String true/false if QVI credential exists or not for the QAR - */ -async function checkLeCredential(aidInfo: string, lePrefix: string, environment: TestEnvironmentPreset) { - // get Clients - const {QAR1} = parseAidInfo(aidInfo); - const [QAR1Client] = await getOrCreateClients(1, [QAR1.salt], environment); - - // Check to see if QVI multisig exists - const qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); - - // Check to see if the QVI credential exists - const qviCredential = await getIssuedCredential( - QAR1Client, - qar1Ms.prefix, - lePrefix, - LE_SCHEMA_SAID - ) - if (!qviCredential) { - return "false-credential-not-found" - } - return "true" -} -const exists: string = await checkLeCredential(aidInfoArg, lePrefix, env); -console.log(exists); diff --git a/qvi-workflow/signify_qvi/qar-check-qvi-credential.ts b/qvi-workflow/signify_qvi/qar-check-qvi-credential.ts deleted file mode 100644 index f502548..0000000 --- a/qvi-workflow/signify_qvi/qar-check-qvi-credential.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { HabState } from "signify-ts"; -import { parseAidInfo } from "./create-aid"; -import { getOrCreateClients } from "./keystore-creation"; -import { TestEnvironmentPreset } from "./resolve-env"; -import { getReceivedCredential } from "./credentials"; - -// process arguments -const args = process.argv.slice(2); -const env = args[0] as 'local' | 'docker'; -const aidInfoArg = args[1] -const qviCredSAID = args[2] - -const QVI_MS_NAME='QVI'; - - -/** - * Checks to see if the QVI credential exists for the QAR - * - * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position - * @param environment the runtime environment to use for resolving environment variables - * @returns {Promise} String true/false if QVI credential exists or not for the QAR - */ -async function checkQviCredential(aidInfo: string, qviCredSAID: string, environment: TestEnvironmentPreset) { - // get Clients - const {QAR1} = parseAidInfo(aidInfo); - const [QAR1Client] = await getOrCreateClients(1, [QAR1.salt], environment); - - // Check to see if QVI multisig exists - let qar1Ms: HabState; - try { - qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); - } catch (e: any) { - return "false-ms-not-found" - } - - // Check to see if the QVI credential exists - let qviCredential = await getReceivedCredential( - QAR1Client, - qviCredSAID - ) - if (!qviCredential) { - return "false-credential-not-found" - } - return "true" -} -const exists: string = await checkQviCredential(aidInfoArg, qviCredSAID, env); -console.log(exists); diff --git a/qvi-workflow/signify_qvi/qars/qar-check-issued-credential.ts b/qvi-workflow/signify_qvi/qars/qar-check-issued-credential.ts new file mode 100644 index 0000000..701d8ed --- /dev/null +++ b/qvi-workflow/signify_qvi/qars/qar-check-issued-credential.ts @@ -0,0 +1,16 @@ +import {checkIssuedCredential, checkReceivedCredential} from "../qvi-operations.ts"; + +/* +Checks the specified multisig with the first QAR to see if a credential has been received + */ + +// process arguments +const args = process.argv.slice(2); +const env = args[0] as 'local' | 'docker'; +const multisigName = args[1] +const aidInfoArg = args[2] +const issueePre = args[3] +const schemaSAID = args[4] + +const exists: string = await checkIssuedCredential(multisigName, aidInfoArg, schemaSAID, issueePre, env); +console.log(exists); diff --git a/qvi-workflow/signify_qvi/qar-check-qvi-multisig.ts b/qvi-workflow/signify_qvi/qars/qar-check-qvi-multisig.ts similarity index 61% rename from qvi-workflow/signify_qvi/qar-check-qvi-multisig.ts rename to qvi-workflow/signify_qvi/qars/qar-check-qvi-multisig.ts index bbafb39..5c276b6 100644 --- a/qvi-workflow/signify_qvi/qar-check-qvi-multisig.ts +++ b/qvi-workflow/signify_qvi/qars/qar-check-qvi-multisig.ts @@ -1,24 +1,24 @@ import { HabState } from "signify-ts"; -import { parseAidInfo } from "./create-aid"; -import { getOrCreateClients } from "./keystore-creation"; -import { TestEnvironmentPreset } from "./resolve-env"; +import { parseAidInfo } from "../create-aid"; +import { getOrCreateClients } from "../keystore-creation"; +import { TestEnvironmentPreset } from "../resolve-env"; // process arguments const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const aidInfoArg = args[1] - -const QVI_MS_NAME='QVI'; +const multisigName = args[1] +const aidInfoArg = args[2] /** * Checks to see if the QVI multisig exists - * + * + * @param multisigName name of the multisig AID * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position * @param environment the runtime environment to use for resolving environment variables * @returns {Promise} String true/false if QVI multisig AID exists or not */ -async function checkQviMultisig(aidInfo: string, environment: TestEnvironmentPreset) { +async function checkQviMultisig(multisigName: string, aidInfo: string, environment: TestEnvironmentPreset) { // get Clients const {QAR1} = parseAidInfo(aidInfo); const [QAR1Client] = await getOrCreateClients(1, [QAR1.salt], environment); @@ -26,11 +26,11 @@ async function checkQviMultisig(aidInfo: string, environment: TestEnvironmentPre // Check to see if QVI multisig exists let qar1Ms: HabState; try { - qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); + qar1Ms = await QAR1Client.identifiers().get(multisigName); } catch (e: any) { return "false" } return "true" } -const exists: string = await checkQviMultisig(aidInfoArg, env); +const exists: string = await checkQviMultisig(multisigName, aidInfoArg, env); console.log(exists); diff --git a/qvi-workflow/signify_qvi/qars/qar-check-received-credential.ts b/qvi-workflow/signify_qvi/qars/qar-check-received-credential.ts new file mode 100644 index 0000000..c6180d5 --- /dev/null +++ b/qvi-workflow/signify_qvi/qars/qar-check-received-credential.ts @@ -0,0 +1,15 @@ +import {checkReceivedCredential} from "../qvi-operations.ts"; + +/* +Checks the specified multisig with the first QAR to see if a credential has been received + */ + +// process arguments +const args = process.argv.slice(2); +const env = args[0] as 'local' | 'docker'; +const multisigName = args[1] +const aidInfoArg = args[2] +const credSAID = args[3] + +const exists: string = await checkReceivedCredential(multisigName, aidInfoArg, credSAID, env); +console.log(exists); diff --git a/qvi-workflow/signify_qvi/qars/qars-admit-ecr-auth-credential.ts b/qvi-workflow/signify_qvi/qars/qars-admit-ecr-auth-credential.ts new file mode 100644 index 0000000..7aaefc9 --- /dev/null +++ b/qvi-workflow/signify_qvi/qars/qars-admit-ecr-auth-credential.ts @@ -0,0 +1,11 @@ +import {checkReceivedCredential} from "../qvi-operations.ts"; + +// process arguments +const args = process.argv.slice(2); +const env = args[0] as 'local' | 'docker'; +const multisigName = args[1] +const aidInfoArg = args[2] +const credSAID = args[3] + +const exists: string = await checkReceivedCredential(multisigName, aidInfoArg, credSAID, env); +console.log(exists); diff --git a/qvi-workflow/signify_qvi/qars-admit-qvi-credential.ts b/qvi-workflow/signify_qvi/qars/qars-admit-qvi-credential.ts similarity index 77% rename from qvi-workflow/signify_qvi/qars-admit-qvi-credential.ts rename to qvi-workflow/signify_qvi/qars/qars-admit-qvi-credential.ts index 4eff030..e06b7b5 100644 --- a/qvi-workflow/signify_qvi/qars-admit-qvi-credential.ts +++ b/qvi-workflow/signify_qvi/qars/qars-admit-qvi-credential.ts @@ -1,22 +1,19 @@ -import fs from "fs"; -import signify, { CreateIdentiferArgs, HabState } from "signify-ts"; -import { createTimestamp, parseAidInfo } from "./create-aid"; -import { getOrCreateAID, getOrCreateClients } from "./keystore-creation"; -import { createAIDMultisig } from "./multisig-creation"; -import { resolveEnvironment, TestEnvironmentPreset } from "./resolve-env"; -import { admitMultisig, getReceivedCredential, waitForCredential } from "./credentials"; -import { waitAndMarkNotification } from "./notifications"; +import {createTimestamp, parseAidInfo} from "../create-aid"; +import {getOrCreateAID, getOrCreateClients} from "../keystore-creation"; +import {resolveEnvironment, TestEnvironmentPreset} from "../resolve-env"; +import {admitMultisig, getReceivedCredential, waitForCredential} from "../credentials"; +import {waitAndMarkNotification} from "../notifications"; // process arguments const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const aidInfoArg = args[1] -const gedaPrefix = args[2] -const qviCredSAID = args[3] +const multisigName = args[1] +const aidInfoArg = args[2] +const gedaPrefix = args[3] +const qviCredSAID = args[4] // resolve witness IDs for QVI multisig AID configuration const {witnessIds} = resolveEnvironment(env); -const QVI_MS_NAME='QVI'; /** @@ -29,7 +26,7 @@ const QVI_MS_NAME='QVI'; * @param environment the runtime environment to use for resolving environment variables * @returns {Promise<{qviMsOobi: string}>} Object containing the delegatee QVI multisig AID OOBI */ -async function admitQviCredential(aidInfo: string, gedaPrefix: string, witnessIds: Array, qviCredSAID: string, environment: TestEnvironmentPreset) { +async function admitQviCredential(multisigName: string, aidInfo: string, gedaPrefix: string, witnessIds: Array, qviCredSAID: string, environment: TestEnvironmentPreset) { // get Clients const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); const [ @@ -54,7 +51,7 @@ async function admitQviCredential(aidInfo: string, gedaPrefix: string, witnessId ]); // Get the QVI multisig AID - const qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); + const qar1Ms = await QAR1Client.identifiers().get(multisigName); // Skip if a QVI AID has already been incepted. let qviCredbyQAR1 = await getReceivedCredential(QAR1Client, qviCredSAID); @@ -99,6 +96,6 @@ async function admitQviCredential(aidInfo: string, gedaPrefix: string, witnessId } } -const admitResult: any = await admitQviCredential(aidInfoArg, gedaPrefix, witnessIds, qviCredSAID, env); +const admitResult: any = await admitQviCredential(multisigName, aidInfoArg, gedaPrefix, witnessIds, qviCredSAID, env); console.log("QVI credential admitted"); diff --git a/qvi-workflow/signify_qvi/qars-and-person-setup.ts b/qvi-workflow/signify_qvi/qars/qars-and-person-setup.ts similarity index 93% rename from qvi-workflow/signify_qvi/qars-and-person-setup.ts rename to qvi-workflow/signify_qvi/qars/qars-and-person-setup.ts index 325f46c..0ed2e67 100755 --- a/qvi-workflow/signify_qvi/qars-and-person-setup.ts +++ b/qvi-workflow/signify_qvi/qars/qars-and-person-setup.ts @@ -1,8 +1,8 @@ -import { getOrCreateContact } from "./agent-contacts"; -import { getOrCreateAID, getOrCreateClients} from "./keystore-creation"; -import { resolveOobi } from "./oobis"; -import { resolveEnvironment, TestEnvironmentPreset } from "./resolve-env"; -import { parseAidInfo } from "./create-aid"; +import { getOrCreateContact } from "../agent-contacts"; +import { getOrCreateAID, getOrCreateClients} from "../keystore-creation"; +import { resolveOobi } from "../oobis"; +import { resolveEnvironment, TestEnvironmentPreset } from "../resolve-env"; +import { parseAidInfo } from "../create-aid"; import fs from 'fs'; /** @@ -167,9 +167,4 @@ async function setupQVIAndPerson(aidInfoArg: string, environment: TestEnvironmen } } const clientInfo: any = await setupQVIAndPerson(aidInfoArg, env); -await fs.writeFile(`${dataDir}/qars-and-person-info.json`, JSON.stringify(clientInfo), (err) => { - if (err) { - console.log(`error writing client info to file: ${err}`); - return - } -}); +await fs.promises.writeFile(`${dataDir}/qars-and-person-info.json`, JSON.stringify(clientInfo)); diff --git a/qvi-workflow/signify_qvi/qars-authorize-endroles-get-qvi-oobi.ts b/qvi-workflow/signify_qvi/qars/qars-authorize-endroles-get-qvi-oobi.ts similarity index 69% rename from qvi-workflow/signify_qvi/qars-authorize-endroles-get-qvi-oobi.ts rename to qvi-workflow/signify_qvi/qars/qars-authorize-endroles-get-qvi-oobi.ts index b27b8d4..ee3a585 100644 --- a/qvi-workflow/signify_qvi/qars-authorize-endroles-get-qvi-oobi.ts +++ b/qvi-workflow/signify_qvi/qars/qars-authorize-endroles-get-qvi-oobi.ts @@ -1,21 +1,21 @@ import { SignifyClient } from "signify-ts"; -import { createTimestamp, parseAidInfo } from "./create-aid"; -import { getOrCreateAID, getOrCreateClients } from "./keystore-creation"; -import { addEndRoleMultisig } from "./multisig-creation"; -import { waitAndMarkNotification } from "./notifications"; -import { waitOperation } from "./operations"; -import { resolveEnvironment, TestEnvironmentPreset } from "./resolve-env"; +import { createTimestamp, parseAidInfo } from "../create-aid"; +import { getOrCreateAID, getOrCreateClients } from "../keystore-creation"; +import { addEndRoleMultisig } from "../multisig-creation"; +import { waitAndMarkNotification } from "../notifications"; +import { waitOperation } from "../operations"; +import { resolveEnvironment, TestEnvironmentPreset } from "../resolve-env"; import fs from 'fs'; // process arguments const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const dataDir = args[1]; -const aidInfoArg = args[2] +const multisigName = args[1] +const dataDir = args[2]; +const aidInfoArg = args[3] // resolve witness IDs for QVI multisig AID configuration const {witnessIds} = resolveEnvironment(env); -const QVI_MS_NAME='QVI'; /** * Authorizes the 'agent' role to each of the three agents used by each of the three SignifyTS participants in the QVI Multisig AID. @@ -25,7 +25,7 @@ const QVI_MS_NAME='QVI'; * @param environment runtime environment to use for resolving environment variables * @returns the three QAR SignifyClient instances */ -async function authorizeAgentEndRoleForQVI(aidInfo: string, witnessIds: Array, environment: TestEnvironmentPreset) { +async function authorizeAgentEndRoleForQVI(multisigName: string, aidInfo: string, witnessIds: Array, environment: TestEnvironmentPreset) { // get Clients const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); const [ @@ -49,13 +49,13 @@ async function authorizeAgentEndRoleForQVI(aidInfo: string, witnessIds: Array { - if (err) { - console.log(`Error writing multisig oobi to file: ${err}`); - } - }); + await fs.promises.writeFile(`${dataDir}/qvi-oobi.json`, JSON.stringify(oobiData)); console.log('QVI multisig oobi has been authorized and generated'); } else { const oobiData = await getQVIMultisigOobi(QAR1Client); - await fs.writeFile(`${dataDir}/qvi-oobi.json`, JSON.stringify(oobiData), (err) => { - if (err) { - console.log(`Error writing multisig oobi to file: ${err}`); - } - }); + await fs.promises.writeFile(`${dataDir}/qvi-oobi.json`, JSON.stringify(oobiData)); console.log("QVI multisig oobi has already been authorized and generated"); } } @@ -133,10 +125,10 @@ async function authorizeAgentEndRoleForQVI(aidInfo: string, witnessIds: Array} Object containing the delegatee QVI multisig AID OOBI */ -async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Array, environment: TestEnvironmentPreset) { +async function createQviMultisig(multisigName: string, aidInfo: string, delpre: string, witnessIds: Array, environment: TestEnvironmentPreset) { // get Clients const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); const [ @@ -54,9 +54,9 @@ async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Ar let qar1Ms, qar2Ms, qar3Ms: HabState; try { - qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); - qar2Ms = await QAR2Client.identifiers().get(QVI_MS_NAME); - qar3Ms = await QAR3Client.identifiers().get(QVI_MS_NAME); + qar1Ms = await QAR1Client.identifiers().get(multisigName); + qar2Ms = await QAR2Client.identifiers().get(multisigName); + qar3Ms = await QAR3Client.identifiers().get(multisigName); // return early if the QVI AID has already been incepted } catch (e: any) { // get QAR keystates for inclusion in the multisig inception event @@ -81,7 +81,7 @@ async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Ar QAR1Client, QAR1Id, [QAR2Id, QAR3Id], - QVI_MS_NAME, + multisigName, kargsMultisigAID, true ); @@ -91,7 +91,7 @@ async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Ar QAR2Client, QAR2Id, [QAR1Id, QAR3Id], - QVI_MS_NAME, + multisigName, kargsMultisigAID ); // change member hab to QAR3 and perform multisig inception @@ -100,13 +100,13 @@ async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Ar QAR3Client, QAR3Id, [QAR1Id, QAR2Id], - QVI_MS_NAME, + multisigName, kargsMultisigAID ); - qar1Ms = await QAR1Client.identifiers().get(QVI_MS_NAME); - qar2Ms = await QAR2Client.identifiers().get(QVI_MS_NAME); - qar3Ms = await QAR3Client.identifiers().get(QVI_MS_NAME); + qar1Ms = await QAR1Client.identifiers().get(multisigName); + qar2Ms = await QAR2Client.identifiers().get(multisigName); + qar3Ms = await QAR3Client.identifiers().get(multisigName); } @@ -119,11 +119,6 @@ async function createQviMultisig(aidInfo: string, delpre: string, witnessIds: Ar } } } -const multisigOobiObj: any = await createQviMultisig(aidInfoArg, delegationPrefix, witnessIds, env); -await fs.writeFile(`${dataDir}/qvi-multisig-info.json`, JSON.stringify(multisigOobiObj), (err) => { - if (err) { - console.log(`error writing client info to file: ${err}`); - return - } -}); +const multisigOobiObj: any = await createQviMultisig(multisigName, aidInfoArg, delegationPrefix, witnessIds, env); +await fs.promises.writeFile(`${dataDir}/qvi-multisig-info.json`, JSON.stringify(multisigOobiObj)); console.log("QVI delegated multisig AID created, waiting for GEDA to confirm delegation..."); diff --git a/qvi-workflow/signify_qvi/qars-le-credential-create.ts b/qvi-workflow/signify_qvi/qars/qars-le-credential-create.ts similarity index 75% rename from qvi-workflow/signify_qvi/qars-le-credential-create.ts rename to qvi-workflow/signify_qvi/qars/qars-le-credential-create.ts index ae4d324..f15051b 100644 --- a/qvi-workflow/signify_qvi/qars-le-credential-create.ts +++ b/qvi-workflow/signify_qvi/qars/qars-le-credential-create.ts @@ -1,23 +1,22 @@ import fs from "fs"; -import signify, { CreateIdentiferArgs, CredentialData, CredentialSubject, HabState, Saider } from "signify-ts"; -import { createTimestamp, parseAidInfo } from "./create-aid"; -import { getOrCreateAID, getOrCreateClients } from "./keystore-creation"; -import { createAIDMultisig } from "./multisig-creation"; -import { resolveEnvironment, TestEnvironmentPreset } from "./resolve-env"; -import { getIssuedCredential, grantMultisig, issueCredentialMultisig } from "./credentials"; -import { waitAndMarkNotification } from "./notifications"; -import { waitOperation } from "./operations"; +import {CredentialData, CredentialSubject} from "signify-ts"; +import {createTimestamp, parseAidInfo} from "../create-aid"; +import {getOrCreateAID, getOrCreateClients} from "../keystore-creation"; +import {resolveEnvironment, TestEnvironmentPreset} from "../resolve-env"; +import {getIssuedCredential, grantMultisig, issueCredentialMultisig} from "../credentials"; +import {waitAndMarkNotification} from "../notifications"; +import {waitOperation} from "../operations"; // process arguments const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const dataDir = args[1]; -const aidInfoArg = args[2] -const lePrefix = args[3] +const multisigName = args[1] +const dataDir = args[2]; +const aidInfoArg = args[3] +const lePrefix = args[4] // resolve witness IDs for QVI multisig AID configuration const {witnessIds} = resolveEnvironment(env); -const QVI_MS_NAME='QVI'; const LE_SCHEMA_SAID = 'ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY'; /** @@ -28,8 +27,7 @@ const LE_SCHEMA_SAID = 'ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY'; * @param environment the runtime environment to use for resolving environment variables * @returns {Promise<{qviMsOobi: string}>} Object containing the delegatee QVI multisig AID OOBI */ -async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: Array, environment: TestEnvironmentPreset) { - console.log(`Creating LE credential and issuing to GIDA ${lePrefix}`) +async function createLeCredential(multisigName: string, aidInfo: string, lePrefix: string, witnessIds: Array, environment: TestEnvironmentPreset) { // get Clients const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); const [ @@ -53,7 +51,7 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: getOrCreateAID(QAR3Client, QAR3.name, kargsAID), ]); - const qviAID = await QAR1Client.identifiers().get(QVI_MS_NAME); + const qviAID = await QAR1Client.identifiers().get(multisigName); // QVI issues a LE vLEI credential to the LE (GIDA in this case). // Skip if the credential has already been issued. @@ -88,9 +86,8 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: else { console.log("LE Credential does not exist, creating and granting"); - const registries:[{name: string, regk: string}] = await QAR1Client.registries().list(QVI_MS_NAME) + const registries:[{name: string, regk: string}] = await QAR1Client.registries().list(multisigName) const qviRegistry = registries[0]; - console.log(`QVI registry: ${qviRegistry.regk}`); let data: string = ""; data = await fs.promises.readFile(`${dataDir}/legal-entity-data.json`, 'utf-8'); @@ -115,7 +112,6 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: e: leCredentialEdge, r: leRules, }; - console.log(`LE credential data: `, kargsIss); const IssOp1 = await issueCredentialMultisig( QAR1Client, QAR1Id, @@ -138,18 +134,15 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: qviAID.name, kargsIss ); - console.log("Credential issued, waiting operations..."); await Promise.all([ waitOperation(QAR1Client, IssOp1), waitOperation(QAR2Client, IssOp2), waitOperation(QAR3Client, IssOp3), ]); - console.log("Operations completed, waiting for notifications..."); await waitAndMarkNotification(QAR1Client, '/multisig/iss'); - console.log("LE credential issued, getting Issued Credential..."); leCredbyQAR1 = await getIssuedCredential( QAR1Client, qviAID.prefix, @@ -170,7 +163,7 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: ); const grantTime = createTimestamp(); - console.log("Granting LE credential..."); + console.log("IPEX Granting LE credential to GIDA (LE)..."); await grantMultisig( QAR1Client, QAR1Id, @@ -200,9 +193,7 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: grantTime ); - console.log("Granting LE credential, waiting operations..."); await waitAndMarkNotification(QAR1Client, '/multisig/exn'); - console.log("LE credential granted"); return { leCredSAID: leCredbyQAR1.sad.d, leCredIssuer: leCredbyQAR1.sad.i, @@ -210,11 +201,6 @@ async function createLeCredential(aidInfo: string, lePrefix: string, witnessIds: } } } -const leCreateResult: any = await createLeCredential(aidInfoArg, lePrefix, witnessIds, env); -await fs.writeFile(`${dataDir}/signify_qvi/qvi_data/le-cred-info.json`, JSON.stringify(leCreateResult), (err) => { - if (err) { - console.log(`error writing LE credential info to file: ${err}`); - return - } -}); +const leCreateResult: any = await createLeCredential(multisigName, aidInfoArg, lePrefix, witnessIds, env); +await fs.promises.writeFile(`${dataDir}/signify_qvi/qvi_data/le-cred-info.json`, JSON.stringify(leCreateResult)); console.log("LE credential created and granted"); diff --git a/qvi-workflow/signify_qvi/qars-person-single-sig-oobis-setup.ts b/qvi-workflow/signify_qvi/qars/qars-person-single-sig-oobis-setup.ts similarity index 91% rename from qvi-workflow/signify_qvi/qars-person-single-sig-oobis-setup.ts rename to qvi-workflow/signify_qvi/qars/qars-person-single-sig-oobis-setup.ts index bad2f4b..807af25 100644 --- a/qvi-workflow/signify_qvi/qars-person-single-sig-oobis-setup.ts +++ b/qvi-workflow/signify_qvi/qars/qars-person-single-sig-oobis-setup.ts @@ -1,9 +1,8 @@ -import { getOrCreateContact } from "./agent-contacts"; -import { getOrCreateClients } from "./keystore-creation"; -import { TestEnvironmentPreset } from "./resolve-env"; -import { OobiInfo } from "./qvi-data"; -import { parseAidInfo } from "./create-aid"; -import { parseOobiInfo } from "./oobis"; +import { getOrCreateContact } from "../agent-contacts"; +import { getOrCreateClients } from "../keystore-creation"; +import { TestEnvironmentPreset } from "../resolve-env"; +import { OobiInfo } from "../qvi-data"; +import { parseAidInfo } from "../create-aid"; // Pull in arguments from the command line and configuration const args = process.argv.slice(2); diff --git a/qvi-workflow/signify_qvi/qars-refresh-geda-multisig-state.ts b/qvi-workflow/signify_qvi/qars/qars-refresh-geda-multisig-state.ts similarity index 84% rename from qvi-workflow/signify_qvi/qars-refresh-geda-multisig-state.ts rename to qvi-workflow/signify_qvi/qars/qars-refresh-geda-multisig-state.ts index 63fb332..3668b8f 100644 --- a/qvi-workflow/signify_qvi/qars-refresh-geda-multisig-state.ts +++ b/qvi-workflow/signify_qvi/qars/qars-refresh-geda-multisig-state.ts @@ -1,8 +1,8 @@ -import { parseAidInfo } from "./create-aid"; -import { getOrCreateClients } from "./keystore-creation"; -import { waitAndMarkNotification } from "./notifications"; -import { waitOperation } from "./operations"; -import { TestEnvironmentPreset } from "./resolve-env"; +import { parseAidInfo } from "../create-aid"; +import { getOrCreateClients } from "../keystore-creation"; +import { waitAndMarkNotification } from "../notifications"; +import { waitOperation } from "../operations"; +import { TestEnvironmentPreset } from "../resolve-env"; const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; diff --git a/qvi-workflow/signify_qvi/qars-registry-create.ts b/qvi-workflow/signify_qvi/qars/qars-registry-create.ts similarity index 70% rename from qvi-workflow/signify_qvi/qars-registry-create.ts rename to qvi-workflow/signify_qvi/qars/qars-registry-create.ts index 43c50ae..09ecc53 100644 --- a/qvi-workflow/signify_qvi/qars-registry-create.ts +++ b/qvi-workflow/signify_qvi/qars/qars-registry-create.ts @@ -1,23 +1,22 @@ import fs from "fs"; -import signify, { CreateIdentiferArgs, HabState, randomNonce } from "signify-ts"; -import { parseAidInfo } from "./create-aid"; -import { getOrCreateAID, getOrCreateClients } from "./keystore-creation"; -import { createAIDMultisig } from "./multisig-creation"; -import { resolveEnvironment, TestEnvironmentPreset } from "./resolve-env"; -import { createRegistryMultisig } from "./credentials"; -import { waitOperation } from "./operations"; -import { waitAndMarkNotification } from "./notifications"; +import {randomNonce} from "signify-ts"; +import {parseAidInfo} from "../create-aid"; +import {getOrCreateAID, getOrCreateClients} from "../keystore-creation"; +import {resolveEnvironment, TestEnvironmentPreset} from "../resolve-env"; +import {createRegistryMultisig} from "../credentials"; +import {waitOperation} from "../operations"; +import {waitAndMarkNotification} from "../notifications"; // process arguments const args = process.argv.slice(2); const env = args[0] as 'local' | 'docker'; -const dataDir = args[1]; -const aidInfoArg = args[2] +const multisigName = args[1]; +const registryName = args[2]; +const dataDir = args[3]; +const aidInfoArg = args[4]; // resolve witness IDs for QVI multisig AID configuration const {witnessIds} = resolveEnvironment(env); -const QVI_MS_NAME='QVI'; -const QVI_REGISTRY_NAME='QVI-REGISTRY' /** @@ -28,7 +27,7 @@ const QVI_REGISTRY_NAME='QVI-REGISTRY' * @param environment the runtime environment to use for resolving environment variables * @returns {Promise<{registryRegk: string}>} Object containing the delegatee QVI multisig AID OOBI */ -async function createQviRegistry(aidInfo: string, witnessIds: Array, environment: TestEnvironmentPreset) { +async function createQviRegistry(multisigName: string, registryName: string, aidInfo: string, witnessIds: Array, environment: TestEnvironmentPreset) { // get Clients const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); const [ @@ -53,14 +52,14 @@ async function createQviRegistry(aidInfo: string, witnessIds: Array, env ]); // Get the QVI multisig AID - const qviAID = await QAR1Client.identifiers().get(QVI_MS_NAME); + const qviAID = await QAR1Client.identifiers().get(multisigName); // Skip if a QVI AID has already been incepted. let [qviRegistrybyQAR1, qviRegistrybyQAR2, qviRegistrybyQAR3] = await Promise.all([ - QAR1Client.registries().list(QVI_MS_NAME), - QAR2Client.registries().list(QVI_MS_NAME), - QAR3Client.registries().list(QVI_MS_NAME), + QAR1Client.registries().list(multisigName), + QAR2Client.registries().list(multisigName), + QAR3Client.registries().list(multisigName), ]); if (qviRegistrybyQAR1.length != 0 && qviRegistrybyQAR2.length != 0 && @@ -76,7 +75,7 @@ async function createQviRegistry(aidInfo: string, witnessIds: Array, env QAR1Id, [QAR2Id, QAR3Id], qviAID, - QVI_REGISTRY_NAME, + registryName, nonce, true ); @@ -85,7 +84,7 @@ async function createQviRegistry(aidInfo: string, witnessIds: Array, env QAR2Id, [QAR1Id, QAR3Id], qviAID, - QVI_REGISTRY_NAME, + registryName, nonce ); const registryOp3 = await createRegistryMultisig( @@ -93,7 +92,7 @@ async function createQviRegistry(aidInfo: string, witnessIds: Array, env QAR3Id, [QAR1Id, QAR2Id], qviAID, - QVI_REGISTRY_NAME, + registryName, nonce ); @@ -116,10 +115,5 @@ async function createQviRegistry(aidInfo: string, witnessIds: Array, env return {registryRegk: qviRegistrybyQAR1[0].regk} } } -const registryInfo: any = await createQviRegistry(aidInfoArg, witnessIds, env); -await fs.writeFile(`${dataDir}/qvi-registry-info.json`, JSON.stringify(registryInfo), (err) => { - if (err) { - console.log(`error writing client info to file: ${err}`); - return - } -}); +const registryInfo: any = await createQviRegistry(multisigName, registryName, aidInfoArg, witnessIds, env); +await fs.promises.writeFile(`${dataDir}/qvi-registry-info.json`, JSON.stringify(registryInfo)); diff --git a/qvi-workflow/signify_qvi/qars-resolve-geda-and-le-oobis.ts b/qvi-workflow/signify_qvi/qars/qars-resolve-geda-and-le-oobis.ts similarity index 89% rename from qvi-workflow/signify_qvi/qars-resolve-geda-and-le-oobis.ts rename to qvi-workflow/signify_qvi/qars/qars-resolve-geda-and-le-oobis.ts index 85387a7..950c6ad 100644 --- a/qvi-workflow/signify_qvi/qars-resolve-geda-and-le-oobis.ts +++ b/qvi-workflow/signify_qvi/qars/qars-resolve-geda-and-le-oobis.ts @@ -1,8 +1,8 @@ -import { getOrCreateContact } from "./agent-contacts"; -import { getOrCreateClients } from "./keystore-creation"; -import { TestEnvironmentPreset } from "./resolve-env"; -import { parseAidInfo } from "./create-aid"; -import { OobiInfo } from "./qvi-data"; +import { getOrCreateContact } from "../agent-contacts"; +import { getOrCreateClients } from "../keystore-creation"; +import { TestEnvironmentPreset } from "../resolve-env"; +import { parseAidInfo } from "../create-aid"; +import { OobiInfo } from "../qvi-data"; // Pull in arguments from the command line and configuration const args = process.argv.slice(2); diff --git a/qvi-workflow/signify_qvi/qars/qars-rotate-qvi-multisig.ts b/qvi-workflow/signify_qvi/qars/qars-rotate-qvi-multisig.ts new file mode 100644 index 0000000..475beb5 --- /dev/null +++ b/qvi-workflow/signify_qvi/qars/qars-rotate-qvi-multisig.ts @@ -0,0 +1,116 @@ +import fs from "fs"; +import signify, {CreateIdentiferArgs, HabState, Serder, Siger, State} from "signify-ts"; +import { parseAidInfo } from "../create-aid"; +import { getOrCreateAID, getOrCreateClients } from "../keystore-creation"; +import { createAIDMultisig } from "../multisig-creation"; +import { resolveEnvironment, TestEnvironmentPreset } from "../resolve-env"; +import {waitAndMarkNotification} from "../notifications.ts"; + +// process arguments +const args = process.argv.slice(2); +const env = args[0] as 'local' | 'docker'; +const multisigName = args[1]; +const dataDir = args[2]; +const aidInfoArg = args[3]; +const delegationPrefix = args[4]; + +// resolve witness IDs for QVI multisig AID configuration +const {witnessIds} = resolveEnvironment(env); + + +/** + * Uses QAR1, QAR2, and QAR3 to create a delegated multisig AID for the QVI delegated from the AID specified by delpre. + * + * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position + * @param delpre The prefix of the delegator to use for the multisig AID + * @param environment the runtime environment to use for resolving environment variables + * @returns {Promise<{qviMsOobi: string}>} Object containing the delegatee QVI multisig AID OOBI + */ +async function rotateMultisig(multisigName: string, aidInfo: string, delpre: string, witnessIds: Array, environment: TestEnvironmentPreset) { + // get Clients + const {QAR1, QAR2, QAR3} = parseAidInfo(aidInfo); + const [ + QAR1Client, + QAR2Client, + QAR3Client, + ] = await getOrCreateClients(3, [QAR1.salt, QAR2.salt, QAR3.salt], environment); + + // get AIDs + const kargsAID = { + toad: witnessIds.length, + wits: witnessIds, + }; + const [ + QAR1Id, + QAR2Id, + QAR3Id, + ] = await Promise.all([ + getOrCreateAID(QAR1Client, QAR1.name, kargsAID), + getOrCreateAID(QAR2Client, QAR2.name, kargsAID), + getOrCreateAID(QAR3Client, QAR3.name, kargsAID), + ]); + + // Create a multisig AID for the QVI. + // Skip if a QVI AID has already been incepted. + + const multisig = await QAR1Client.identifiers().get(multisigName); + + // get QAR keystates for inclusion in the multisig inception event + const rstates = [QAR1Id.state, QAR2Id.state, QAR3Id.state]; + const states = rstates; + + const rotateOp = await QAR1Client.identifiers().rotate( + multisigName, {states: states} + ); + + // add signature attachments to the exn message + + const {payload, rotationEmbeds, recipients} = createMultisigExnData(states, rotateOp.serder, rotateOp.sigs); + + await QAR1Client + .exchanges() + .send( + QAR1.name, + multisigName, + QAR1Id, + '/multisig/rotate', + payload, + rotationEmbeds, + recipients + ); + + await Promise.all([ + waitAndMarkNotification(QAR1Client, '/multisig/rot'), + waitAndMarkNotification(QAR2Client, '/multisig/rot'), + waitAndMarkNotification(QAR3Client, '/multisig/rot'), + ]); +} + +/** + * Prepares rotation payload, signature embeds, and a recipient list based on the rotation serder and key states. + * Used in the exchange message ('exn') sent to multisig participants to perform the multisig rotation. + * @param keyStates + * @param rotation + * @param sigs + */ +function createMultisigExnData(keyStates: State[], rotation: Serder, sigs: string[]) { + // add signature attachments to the exn message + const sigers: Siger[] = sigs.map( + (sig) => new signify.Siger({qb64: sig}) + ); + const sigMessageStream = signify.d(signify.messagize(rotation, sigers)); + const attachmentStream = sigMessageStream.substring(rotation.size); // extract just the attachments + const rotationEmbeds = { + rot: [rotation, attachmentStream] + }; + // signing member IDs (signing this rotation - must satisfy the current signing threshold and prior next) + const smids = keyStates.map((state: State) => state['i']); + // rotation member IDs (members that can sign the next rotation) + const rmids = keyStates.map((state: State) => state['i']); + const recipients = keyStates.map((state: State) => state['i']); + const payload = { gid: rotation.pre, smids, rmids}; + return {payload, rotationEmbeds, recipients}; +} + +const multisigOobiObj: any = await rotateMultisig(multisigName, aidInfoArg, delegationPrefix, witnessIds, env); +console.log("QVI delegated multisig rotated, waiting for GEDA to confirm rotation..."); diff --git a/qvi-workflow/signify_qvi/qvi-operations.ts b/qvi-workflow/signify_qvi/qvi-operations.ts new file mode 100644 index 0000000..14de9f1 --- /dev/null +++ b/qvi-workflow/signify_qvi/qvi-operations.ts @@ -0,0 +1,63 @@ +import {getOrCreateClients} from "./keystore-creation.ts"; +import {parseAidInfo} from "./create-aid.ts"; +import {TestEnvironmentPreset} from "./resolve-env.ts"; +import {getIssuedCredential, getReceivedCredential} from "./credentials.ts"; + +/** + * Checks to see if the QVI credential exists for the QAR + * + * @param multisigName name of the multisig identity to use to check for credentials + * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position + * @param schemaSAID the SAID of the ACDC credential schema to use to filter the credential search + * @param issueePrefix identifier prefix for the Legal Entity multisig AID who would be the recipient, or issuee, of the LE credential. + * @param environment the runtime environment to use for resolving environment variables + * @returns {Promise} String true/false if QVI credential exists or not for the QAR + */ +export async function checkIssuedCredential(multisigName: string, aidInfo: string, schemaSAID: string, issueePrefix: string, environment: TestEnvironmentPreset) { + // get Clients + const {QAR1} = parseAidInfo(aidInfo); + const [QAR1Client] = await getOrCreateClients(1, [QAR1.salt], environment); + + // Check to see if QVI multisig exists + const multisig = await QAR1Client.identifiers().get(multisigName); + + // Check to see if the QVI credential exists + const issuedCred = await getIssuedCredential( + QAR1Client, + multisig.prefix, + issueePrefix, + schemaSAID + ) + if (!issuedCred) { + return "false-credential-not-found" + } + return "true" +} + +/** + * Checks to see if the QVI credential exists for the QAR + * + * @param multisigName name of the multisig identity to use to check for credentials + * @param aidInfo A comma-separated list of AID information that is further separated by a pipe character for name, salt, and position + * @param credSAID The SAID of the credential issuance to check for. + * @param environment the runtime environment to use for resolving environment variables + * @returns {Promise} String true/false if QVI credential exists or not for the QAR + */ +export async function checkReceivedCredential(multisigName: string, aidInfo: string, credSAID: string, environment: TestEnvironmentPreset) { + // get Clients + const {QAR1} = parseAidInfo(aidInfo); + const [QAR1Client] = await getOrCreateClients(1, [QAR1.salt], environment); + + // Check to see if QVI multisig exists + let multisig = await QAR1Client.identifiers().get(multisigName); + + // Check to see if the QVI credential exists + let receivedCred = await getReceivedCredential( + QAR1Client, + credSAID + ) + if (!receivedCred) { + return "false-credential-not-found" + } + return "true" +} \ No newline at end of file