Skip to content

Commit

Permalink
deploy the rp & civic canister using the local ic_rootkey using scrip…
Browse files Browse the repository at this point in the history
…ts from dfinity
  • Loading branch information
happyhackerbird committed May 7, 2024
1 parent 09b8b23 commit 9e9c58c
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 10 deletions.
133 changes: 133 additions & 0 deletions src/civic_canister_backend/deploy-civic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env bash

set -euo pipefail

#########
# USAGE #
#########

function title() {
echo "Provisioning issuer canister" >&2
}

function usage() {
cat >&2 << EOF
Usage:
$0 [--ii-canister-id CANISTER_ID] [--dfx-network NETWORK]
Options:
--ii-canister-id CANISTER_ID The canister ID to use as IDP, defaults to the local internet_identity canister
--dfx-network NETWORK The network to use (typically "local" or "ic"), defaults to "local"
--issuer-canister CANISTER The canister to configure (name or canister ID), defaults to "issuer"
EOF
}

function help() {
cat >&2 << EOF
The issuer canister needs some information to operate correctly. This reads data
from the replica to ensure the issuer is provisioned correctly.
EOF
}

II_CANISTER_ID=
DFX_NETWORK=

while [[ $# -gt 0 ]]
do
case "$1" in
-h|--help)
title
usage
help
exit 0
;;
--ii-canister-id)
II_CANISTER_ID="${2:?missing value for '--ii-canister-id'}"
shift; # shift past --ii-canister-id & value
shift;
;;
--dfx-network)
DFX_NETWORK="${2:?missing value for '--dfx-network'}"
shift; # shift past --dfx-network & value
shift;
;;
--issuer-canister)
ISSUER_CANISTER_ID="${2:?missing value for '--issuer-canister-id'}"
shift; # shift past --issuer-canister & value
shift;
;;
*)
echo "ERROR: unknown argument $1"
usage
echo
echo "Use '$0 --help' for more information"
exit 1
;;
esac
done

# Make sure we always run from the repo's root
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPTS_DIR/.."

DFX_NETWORK="${DFX_NETWORK:-local}"
II_CANISTER_ID="${II_CANISTER_ID:-$(dfx canister id internet_identity --network "$DFX_NETWORK")}"
ISSUER_CANISTER_ID="${ISSUER_CANISTER_ID:-$(dfx canister id civic_canister_backend --network "$DFX_NETWORK")}"
if [ "$DFX_NETWORK" = "local" ]; then
REPLICA_SERVER_PORT=$(dfx info webserver-port)
ISSUER_DERIVATION_ORIGIN="http://${ISSUER_CANISTER_ID}.localhost:${REPLICA_SERVER_PORT}"
ISSUER_FRONTEND_HOSTNAME="http://${ISSUER_CANISTER_ID}.localhost:${REPLICA_SERVER_PORT}"
fi
if [ "$DFX_NETWORK" = "devenv_llorenc" ]; then
ISSUER_DERIVATION_ORIGIN="https://${ISSUER_CANISTER_ID}.llorenc-ingress.devenv.dfinity.network"
ISSUER_FRONTEND_HOSTNAME="https://${ISSUER_CANISTER_ID}.llorenc-ingress.devenv.dfinity.network"
fi
if [ "$DFX_NETWORK" = "mainnet" ]; then
ISSUER_DERIVATION_ORIGIN="https://${ISSUER_CANISTER_ID}.icp0.io"
ISSUER_FRONTEND_HOSTNAME="https://metaissuer.vc"
fi
if [ "$DFX_NETWORK" = "ic_test" ]; then
ISSUER_DERIVATION_ORIGIN="https://${ISSUER_CANISTER_ID}.icp0.io"
ISSUER_FRONTEND_HOSTNAME="https://${ISSUER_CANISTER_ID}.icp0.io"
fi

echo "Using DFX network: $DFX_NETWORK" >&2
echo "Using II canister: $II_CANISTER_ID" >&2
echo "Using issuer canister: $ISSUER_CANISTER_ID" >&2
echo "Using derivation origin: $ISSUER_DERIVATION_ORIGIN" >&2
echo "Using frontend hostname: $ISSUER_FRONTEND_HOSTNAME" >&2

# At the time of writing dfx outputs incorrect JSON with dfx ping (commas between object
# entries are missing).
# In order to read the root key we grab the array from the '"root_key": [...]' bit, the brackets
# to match what candid expects ({}), replace the commas between array entries to match
# what candid expects (semicolon) and annotate the numbers with their type (otherwise dfx assumes 'nat'
# instead of 'nat8').
rootkey_did=$(dfx ping "$DFX_NETWORK" \
| sed -n 's/.*"root_key": \[\(.*\)\].*/{\1}/p' \
| sed 's/\([0-9][0-9]*\)/\1:nat8/g' \
| sed 's/,/;/g')

echo "Parsed rootkey: ${rootkey_did:0:20}..." >&2

echo "Using II canister: $II_CANISTER_ID" >&2

# Add also dev server to alternative origins when deploying locally
# if [ "$DFX_NETWORK" = "local" ]; then
# ALTERNATIVE_ORIGINS="\"$ISSUER_FRONTEND_HOSTNAME\",\"http://localhost:5173\","
# else
# ALTERNATIVE_ORIGINS="\"$ISSUER_FRONTEND_HOSTNAME\","
# fi

# Adjust issuer's .well-known/ii-alternative-origins to contain FE-hostname of local/dev deployments.
# We had a problem with `sed` command in CI. This is a hack to make it work locally and in CI.
# mv ./issuer/frontend/static/.well-known/ii-alternative-origins ./ii-alternative-origins-template
# cat ./ii-alternative-origins-template | sed "s+ISSUER_FE_HOSTNAME_PLACEHOLDER+$ALTERNATIVE_ORIGINS+g" > ./issuer/frontend/static/.well-known/ii-alternative-origins
# rm ./ii-alternative-origins-template

dfx deploy civic_canister_backend --network "$DFX_NETWORK" --argument '(opt record { idp_canister_ids = vec{ principal "'"$II_CANISTER_ID"'" }; ic_root_key_der = vec '"$rootkey_did"'; derivation_origin = "'"$ISSUER_DERIVATION_ORIGIN"'"; frontend_hostname = "'"$ISSUER_FRONTEND_HOSTNAME"'"; })'

# Revert changes
# git checkout ./issuer/frontend/static/.well-known/ii-alternative-origins
11 changes: 6 additions & 5 deletions src/civic_canister_backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ fn config_memory() -> Memory {
use ic_cdk::println;

#[derive(CandidType, Deserialize)]
#[derive(Debug)]
struct IssuerConfig {
/// Root of trust for checking canister signatures.
ic_root_key_raw: Vec<u8>,
Expand Down Expand Up @@ -124,7 +123,7 @@ impl Default for IssuerConfig {
Self {
ic_root_key_raw: extract_raw_root_pk_from_der(IC_ROOT_PK_DER)
.expect("failed to extract raw root pk from der"),
idp_canister_ids: vec![Principal::from_text(PROD_II_CANISTER_ID).unwrap()],
idp_canister_ids: vec![Principal::from_text(LOCAL_II_CANISTER_ID).unwrap()],
derivation_origin: derivation_origin.clone(),
frontend_hostname: derivation_origin,
}
Expand Down Expand Up @@ -185,14 +184,13 @@ fn apply_config(init: IssuerInit) {
}

fn authorize_vc_request(

alias: &SignedIdAlias,
expected_vc_subject: &Principal,
current_time_ns: u128,
) -> Result<AliasTuple, IssueCredentialError> {
CONFIG.with_borrow(|config| {
let config = config.get();

// check if the ID alias is legitimate and was issued by the internet identity canister
for idp_canister_id in &config.idp_canister_ids {
if let Ok(alias_tuple) = get_verified_id_alias_from_jws(
Expand All @@ -216,13 +214,14 @@ fn authorize_vc_request(
async fn prepare_credential(
req: PrepareCredentialRequest,
) -> Result<PreparedCredentialData, IssueCredentialError> {

println!("req: {:?}", req);
// here we need to acquire the user principal and use it instead of caller
let alias_tuple = match authorize_vc_request(&req.signed_id_alias, &caller(), time().into()) {
Ok(alias_tuple) => alias_tuple,
Err(err) => return Err(err),
};


let credential_jwt = match prepare_credential_jwt(&req.credential_spec, &alias_tuple) {
Ok(credential) => credential,
Err(err) => return Result::<PreparedCredentialData, IssueCredentialError>::Err(err),
Expand All @@ -237,6 +236,8 @@ async fn prepare_credential(
});
update_root_hash();

println!("returning");

// return a prepared context
Ok(PreparedCredentialData {
prepared_context: Some(ByteBuf::from(credential_jwt.as_bytes())),
Expand Down
123 changes: 123 additions & 0 deletions src/relying_canister_frontend/deploy-rp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env bash

set -euo pipefail

#########
# USAGE #
#########

function title() {
echo "Provisioning relying party canister" >&2
}

function usage() {
cat >&2 << EOF
Usage:
$0 [--ii-canister-id CANISTER_ID] [--dfx-network NETWORK]
Options:
--dfx-network NETWORK The network to use (typically "local" or "ic"), defaults to "local"
--ii-canister-id CANISTER_ID The canister id of II instance, defaults to the local internet_identity canister
--issuer-canister-id CANISTER_ID The canister id of the issuer, defaults to the local issuer canister
EOF
}

function help() {
cat >&2 << EOF
The issuer canister needs some information to operate correctly. This reads data
from the replica to ensure the issuer is provisioned correctly.
EOF
}

DFX_NETWORK=
II_CANISTER_ID=
ISSUER_CANISTER_ID=

while [[ $# -gt 0 ]]
do
case "$1" in
-h|--help)
title
usage
help
exit 0
;;
--dfx-network)
DFX_NETWORK="${2:?missing value for '--dfx-network'}"
shift; # shift past --dfx-network & value
shift;
;;
--ii-canister-id)
II_CANISTER_ID="${2:?missing value for '--ii-canister-id'}"
shift; # shift past argument name & value
shift;
;;
--issuer-canister-id)
ISSUER_CANISTER_ID="${2:?missing value for '--issuer-canister-id'}"
shift; # shift past argument name & value
shift;
;;
*)
echo "ERROR: unknown argument $1"
usage
echo
echo "Use '$0 --help' for more information"
exit 1
;;
esac
done

# Make sure we always run from the repo's root
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPTS_DIR/.."

# URL used by II-issuer in the id_alias-verifiable credentials (hard-coded in II)
II_VC_URL="https://identity.ic0.app/"
# URL used by meta-issuer in the issued verifiable credentials (hard-coded in meta-issuer)
ISSUER_VC_URL="https://metaissuer.vc/"

DFX_NETWORK="${DFX_NETWORK:-local}"
RP_CANISTER_ID="$(dfx canister id relying_canister_frontend --network "$DFX_NETWORK")"
II_CANISTER_ID="${II_CANISTER_ID:-$(dfx canister id internet_identity --network "$DFX_NETWORK")}"
ISSUER_CANISTER_ID="${ISSUER_CANISTER_ID:-$(dfx canister id meta_issuer --network "$DFX_NETWORK")}"

echo "Using DFX network: $DFX_NETWORK" >&2
echo "Using RP canister: $RP_CANISTER_ID" >&2
echo "Using II vc_url: $II_VC_URL" >&2
echo "Using II canister: $II_CANISTER_ID" >&2
echo "Using issuer vc_url: $ISSUER_VC_URL" >&2
echo "Using issuer canister: $ISSUER_CANISTER_ID" >&2

# At the time of writing dfx outputs incorrect JSON with dfx ping (commas between object
# entries are missing).
# In order to read the root key we grab the array from the '"root_key": [...]' bit, the brackets
# to match what candid expects ({}), replace the commas between array entries to match
# what candid expects (semicolon) and annotate the numbers with their type (otherwise dfx assumes 'nat'
# instead of 'nat8').
rootkey_did=$(dfx ping "$DFX_NETWORK" \
| sed -n 's/.*"root_key": \[\(.*\)\].*/{\1}/p' \
| sed 's/\([0-9][0-9]*\)/\1:nat8/g' \
| sed 's/,/;/g')

echo "Parsed rootkey: ${rootkey_did:0:20}..." >&2

# Add dev server to alternative origins when deploying locally
# if [ "$DFX_NETWORK" = "local" ]; then
# # Adjust issuer's .well-known/ii-alternative-origins to contain FE-hostname of local/dev deployments.
# # We had a problem with `sed` command in CI. This is a hack to make it work locally and in CI.
# mv ./rp/frontend/static/.well-known/ii-alternative-origins ./ii-alternative-origins-template
# cat ./ii-alternative-origins-template | sed "s+RP_FE_HOSTNAME_PLACEHOLDER+\"http://localhost:5173\",+g" > ./rp/frontend/static/.well-known/ii-alternative-origins
# rm ./ii-alternative-origins-template
# else
# mv ./rp/frontend/static/.well-known/ii-alternative-origins ./ii-alternative-origins-template
# cat ./ii-alternative-origins-template | sed "s+RP_FE_HOSTNAME_PLACEHOLDER++g" > ./rp/frontend/static/.well-known/ii-alternative-origins
# rm ./ii-alternative-origins-template
# fi

dfx deploy relying_canister_frontend --network "$DFX_NETWORK" --argument '(opt record { issuers = vec{ record{ vc_url = "'"$ISSUER_VC_URL"'"; canister_id = principal "'"$ISSUER_CANISTER_ID"'" }}; ic_root_key_der = vec '"$rootkey_did"'; ii_vc_url = "'"$II_VC_URL"'"; ii_canister_id = principal"'"$II_CANISTER_ID"'"; })'

# Revert changes
# git checkout ./rp/frontend/static/.well-known/ii-alternative-origins
9 changes: 4 additions & 5 deletions src/relying_canister_frontend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { AuthClient } from "@dfinity/auth-client";
import type { Principal } from "@dfinity/principal";
import {_SERVICE} from "../../declarations/civic_canister_backend/civic_canister_backend.did"

const canisterId = "b77ix-eeaaa-aaaaa-qaada-cai" //hardcoded civic canister id, get it using dfx canister id civic_canister_backend
const canisterId = "bkyz2-fmaaa-aaaaa-qaaaq-cai" //hardcoded civic canister id, get it using dfx canister id civic_canister_backend

const local_ii_url = `http://${process.env.INTERNET_IDENTITY_CANISTER_ID}.localhost:4943`;

let principal: Principal | undefined;
let authClient: AuthClient;

document.body.onload = () => {
let iiUrl;
Expand All @@ -24,7 +23,7 @@ document.body.onload = () => {
};

document.getElementById("loginBtn")?.addEventListener("click", async () => {
authClient = await AuthClient.create();
const authClient = await AuthClient.create();
const iiUrl = document.querySelector<HTMLInputElement>("#iiUrl")!.value;
await new Promise<void>((resolve, reject) => {
authClient.login({
Expand All @@ -49,12 +48,12 @@ const credentialData = {
credentialType: 'VerifiedAdult',
arguments: {}
},
credentialSubject: 'r2hdh-fwdj2-u2l6t-hsprj-zbb2a-6xqm5-keuie-cyz53-hzv4r-5fsgv-eae'
credentialSubject: principal?.toText()
};

// Define the issuer data
const issuerData = {
"origin": "http://b77ix-eeaaa-aaaaa-qaada-cai.localhost:4943",
"origin": "http://bkyz2-fmaaa-aaaaa-qaaaq-cai.localhost:4943",
"canisterId": canisterId
};

Expand Down

0 comments on commit 9e9c58c

Please sign in to comment.