From 233577b5c9c3d5b898ddb3e5a4415bbd4eeae010 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Thu, 11 Jul 2024 13:26:39 -0700 Subject: [PATCH 01/20] reorder params, add location, name variables Signed-off-by: steve lasker --- action.yml | 36 ++++++++++++++------------- scitt-scripts/entrypoint.sh | 49 +++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/action.yml b/action.yml index 5b8d8c4..d26820e 100644 --- a/action.yml +++ b/action.yml @@ -1,34 +1,35 @@ name: 'DataTrails SCITT API' description: 'Register, Get Receipts and Query Feeds from the DataTrails SCITT API' inputs: + content-type: + description: 'The payload content type (iana mediaType) to be registered on the SCITT Service (eg: application/spdx+json, application/vnd.cyclonedx+json, Scan Result, Attestation)' + required: true datatrails-client_id: description: 'The CLIENT_ID used to access the DataTrails SCITT APIs' required: true datatrails-secret: description: 'The SECRET used to access the DataTrails SCITT APIs' required: true - subject: - description: 'Unique ID for the collection of statements about an artifact' - required: true payload: description: 'The payload file to be registered on the SCITT Service (eg: SBOM, Scan Result, Attestation)' required: true - content-type: - description: 'The payload content type (iana mediaType) to be registered on the SCITT Service (eg: application/spdx+json, application/vnd.cyclonedx+json, Scan Result, Attestation)' - required: true - signed-statement-file: - description: 'File representing the signed SCITT Statement that will be registered on SCITT.' + payload_location: + description: 'Optional location the content of the payload may be stored.' required: false - default: 'signed-statement.cbor' receipt-file: description: 'The file to save the cbor receipt' required: false default: 'receipt.cbor' - signing-key-file: - description: 'The .pem file used to sign the statement' - required: true - issuer: - description: 'The name of the issuer, set to CTW_Claims:iss' + signed-statement-file: + description: 'File representing the signed SCITT Statement that will be registered on SCITT.' + required: false + default: 'signed-statement.cbor' + skip-receipt: + description: 'To skip receipt retrieval, set to 1' + required: false + default: '0' + subject: + description: 'Unique ID for the collection of statements about an artifact' required: true outputs: token: # id of output @@ -37,12 +38,13 @@ runs: using: 'docker' image: 'Dockerfile' args: + - ${{ inputs.content-type }} - ${{ inputs.datatrails-client_id }} - ${{ inputs.datatrails-secret }} + - ${{ inputs.issuer }} - ${{ inputs.subject }} - ${{ inputs.payload }} - - ${{ inputs.content-type }} - - ${{ inputs.signed-statement-file }} + - ${{ inputs.payload-location}} - ${{ inputs.receipt-file }} + - ${{ inputs.signed-statement-file }} - ${{ inputs.signing-key-file }} - - ${{ inputs.issuer }} diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 277d251..9b1823f 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -1,36 +1,47 @@ #!/bin/bash -l # Uncomment for debugging -# echo "datatrails-client_id: " ${1} -# echo "datatrails-secret: " ${2} -# echo "subject: " ${3} -# echo "payload: " ${4} -# echo "content-type: " ${5} -# echo "signed-statement-file: " ${6} -# echo "receipt-file: " ${7} -# echo "signing-key-file: " ${8} -# echo "issuer: " ${9} - -SIGNED_STATEMENT_FILE=./${6} +# echo "content-type: " ${1} +# echo "datatrails-client_id: " ${2} +# echo "datatrails-secret: " ${3} +# echo "issuer: " ${4} +# echo "subject: " ${5} +# echo "payload_file: " ${6} +# echo "payload-location: " ${7} +# echo "receipt-file: " ${8} +# echo "signed-statement-file: " ${9} +# echo "signing-key-file: " ${10} +# echo "skip-receipt: " ${11} + +CONTENT_TYPE=${1} +DATATRAILS_CLIENT_ID=${2} +DATATRAILS_SECRET_ID=${3} +ISSUER=${4} +SUBJECT=${5} +PAYLOAD=${6} +PAYLOAD_LOCATION=${7} +RECEIPT_FILE=${8} +SIGNED_STATEMENT_FILE=${9} +SIGNING_KEY_FILE=${10} + TOKEN_FILE="./bearer-token.txt" -SUBJECT=${3} + echo "Create an access token" -/scripts/create-token.sh ${1} ${2} $TOKEN_FILE +/scripts/create-token.sh ${DATATRAILS_CLIENT_ID} ${DATATRAILS_SECRET_ID} $TOKEN_FILE # ls -a -# echo "PWD: $PWD" # ls -la $TOKEN_FILE echo "Create a Signed Statement, hashing the payload" python /scripts/create_hashed_signed_statement.py \ - --subject ${3} \ - --payload ${4} \ - --content-type ${5} \ + --subject $SUBJECT \ + --payload $PAYLOAD_FILE \ + --content-type $CONTENT_TYPE \ --output-file $SIGNED_STATEMENT_FILE \ - --signing-key-file ${8} \ - --issuer ${9} + --signing-key-file $SIGNING_KEY_FILE \ + --issuer $ISSUER echo "Register the SCITT SIgned Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" From 3d5e751511f19569079729ac45d526e681716eb5 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Thu, 11 Jul 2024 17:31:35 -0700 Subject: [PATCH 02/20] Update HEADER parameters for private use Signed-off-by: steve lasker --- scitt-scripts/create_hashed_signed_statement.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index 5df2048..3f7e079 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -36,8 +36,10 @@ # Signed Hash envelope header labels from: # https://github.com/OR13/draft-steele-cose-hash-envelope/blob/main/draft-steele-cose-hash-envelope.md -HEADER_LABEL_PAYLOAD_HASH_ALGORITHM = 998 -HEADER_LABEL_LOCATION = 999 +# pre-adoption/private use parameters +# https://www.iana.org/assignments/cose/cose.xhtml#header-parameters +HEADER_LABEL_PAYLOAD_HASH_ALGORITHM = -6800 +HEADER_LABEL_LOCATION = -6801 def open_signing_key(key_file: str) -> SigningKey: From ce13b29669eafc9f1e88a385838339bc067e589b Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 12 Jul 2024 17:43:36 -0700 Subject: [PATCH 03/20] Update params Signed-off-by: steve lasker --- action.yml | 15 +++++++++------ scitt-scripts/entrypoint.sh | 26 +++++++++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/action.yml b/action.yml index d26820e..3e646c7 100644 --- a/action.yml +++ b/action.yml @@ -10,14 +10,17 @@ inputs: datatrails-secret: description: 'The SECRET used to access the DataTrails SCITT APIs' required: true - payload: + issuer: + description: 'The name of the issuer, set to CTW_Claims:iss' + required: true + payload-file: description: 'The payload file to be registered on the SCITT Service (eg: SBOM, Scan Result, Attestation)' required: true - payload_location: + payload-location: description: 'Optional location the content of the payload may be stored.' required: false receipt-file: - description: 'The file to save the cbor receipt' + description: 'The filename to save the cbor receipt' required: false default: 'receipt.cbor' signed-statement-file: @@ -42,9 +45,9 @@ runs: - ${{ inputs.datatrails-client_id }} - ${{ inputs.datatrails-secret }} - ${{ inputs.issuer }} - - ${{ inputs.subject }} - - ${{ inputs.payload }} + - ${{ inputs.payload-file }} - ${{ inputs.payload-location}} - ${{ inputs.receipt-file }} - ${{ inputs.signed-statement-file }} - - ${{ inputs.signing-key-file }} + - ${{ inputs.skip-receipt }} + - ${{ inputs.subject }} diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 9b1823f..3b95369 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -6,7 +6,7 @@ # echo "datatrails-secret: " ${3} # echo "issuer: " ${4} # echo "subject: " ${5} -# echo "payload_file: " ${6} +# echo "payload_file: " ${6} # echo "payload-location: " ${7} # echo "receipt-file: " ${8} # echo "signed-statement-file: " ${9} @@ -23,6 +23,7 @@ PAYLOAD_LOCATION=${7} RECEIPT_FILE=${8} SIGNED_STATEMENT_FILE=${9} SIGNING_KEY_FILE=${10} +SKIP_RECEIPT=${11} TOKEN_FILE="./bearer-token.txt" @@ -43,6 +44,11 @@ python /scripts/create_hashed_signed_statement.py \ --signing-key-file $SIGNING_KEY_FILE \ --issuer $ISSUER +if [ ! -f $SIGNED_STATEMENT_FILE ]; then + echo "ERROR: Signed Statement: [$SIGNED_STATEMENT_FILE] Not found!" + return 404 +fi + echo "Register the SCITT SIgned Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" RESPONSE=$(curl -X POST -H @$TOKEN_FILE \ @@ -54,10 +60,20 @@ echo "RESPONSE: $RESPONSE" OPERATION_ID=$(echo $RESPONSE | jq -r .operationID) echo "OPERATION_ID: $OPERATION_ID" -# echo "call: /scitt-scripts/check_operation_status.py" -# python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE +echo "skip-receipt: $SKIP_RECEIPT" + +if [ -n "$SKIP_RECEIPT" ] && [ $SKIP_RECEIPT = "1" ]; then + echo "skipping receipt retrieval" +else + echo "Download the SCITT Receipt: $RECEIPT_FILE" + echo "call: /scripts/check_operation_status.py" + python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE -# RESPONSE=$(python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE) -# ENTRY_ID=$(echo $RESPONSE | jq -r .entryID) + ENTRY_ID=$(python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE) + echo "ENTRY_ID :" $ENTRY_ID + curl -H @$TOKEN_FILE \ + https://app.datatrails.ai/archivist/v1/publicscitt/entries/$ENTRY_ID/receipt \ + -o $RECEIPT_FILE +fi # curl https://app.datatrails.ai/archivist/v2/publicassets/-/events?event_attributes.subject=$SUBJECT | jq From 1e70ffe29384bdc8a73dc000857e9e2339bf5892 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 12 Jul 2024 18:20:26 -0700 Subject: [PATCH 04/20] Re-add signing-key-file Signed-off-by: steve lasker --- action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yml b/action.yml index 3e646c7..8299773 100644 --- a/action.yml +++ b/action.yml @@ -27,6 +27,9 @@ inputs: description: 'File representing the signed SCITT Statement that will be registered on SCITT.' required: false default: 'signed-statement.cbor' + signing-key-file: + description: 'The .pem file used to sign the statement' + required: true skip-receipt: description: 'To skip receipt retrieval, set to 1' required: false @@ -49,5 +52,6 @@ runs: - ${{ inputs.payload-location}} - ${{ inputs.receipt-file }} - ${{ inputs.signed-statement-file }} + - ${{ inputs.signing-key-file }} - ${{ inputs.skip-receipt }} - ${{ inputs.subject }} From 2c79a69a6344807475da28198b69c005467c731a Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 12 Jul 2024 18:36:04 -0700 Subject: [PATCH 05/20] Fix param name Signed-off-by: steve lasker --- scitt-scripts/create_hashed_signed_statement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index 3f7e079..c0907f6 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -200,7 +200,7 @@ def main(): payload = open_payload(args.payload_file) signed_statement = create_hashed_signed_statement( - signing_key, + signing_key-file, payload, args.subject, args.issuer, From 9371f7625b3b5171603514b69869d08f0a4b0912 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 12 Jul 2024 18:43:58 -0700 Subject: [PATCH 06/20] Parm ordering, naming Signed-off-by: steve lasker --- .../create_hashed_signed_statement.py | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index c0907f6..dd2d8d6 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -141,57 +141,57 @@ def main(): parser = argparse.ArgumentParser(description="Create a signed statement.") - # signing key file + # content-type parser.add_argument( - "--signing-key-file", + "--content-type", type=str, - help="filepath to the stored ecdsa P-256 signing key, in pem format.", - default="scitt-signing-key.pem", + help="The iana.org media type for the payload", + default="application/json", ) - # payload-file (a reference to the file that will become the payload of the SCITT Statement) + # issuer parser.add_argument( - "--payload-file", + "--issuer", type=str, - help="filepath to the content that will be hashed into the payload of the SCITT Statement.", - default="scitt-payload.json", + help="issuer who owns the signing key.", ) - # content-type + # output file parser.add_argument( - "--content-type", + "--output-file", type=str, - help="The iana.org media type for the payload", - default="application/json", + help="name of the output file to store the signed statement.", + default="signed-statement.cbor", ) - # subject + # payload-file (a reference to the file that will become the payload of the SCITT Statement) parser.add_argument( - "--subject", + "--payload-file", type=str, - help="subject to correlate statements made about an artifact.", + help="filepath to the content that will be hashed into the payload of the SCITT Statement.", + default="scitt-payload.json", ) - # issuer + # payload-location parser.add_argument( - "--issuer", + "--payload-location", type=str, - help="issuer who owns the signing key.", + help="location hint for the original statement that was hashed.", ) - # location hint + # signing key file parser.add_argument( - "--location-hint", + "--signing-key-file", type=str, - help="location hint for the original statement that was hashed.", + help="filepath to the stored ecdsa P-256 signing key, in pem format.", + default="scitt-signing-key.pem", ) - # output file + # subject parser.add_argument( - "--output-file", + "--subject", type=str, - help="name of the output file to store the signed statement.", - default="signed-statement.cbor", + help="subject to correlate statements made about an artifact.", ) args = parser.parse_args() @@ -200,12 +200,12 @@ def main(): payload = open_payload(args.payload_file) signed_statement = create_hashed_signed_statement( - signing_key-file, + signing_key_file, payload, + args.payload_location, args.subject, args.issuer, args.content_type, - args.location_hint, ) with open(args.output_file, "wb") as output_file: From ab02c15ee2efa9e56c78deed5facc5612576a3cb Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 13:05:25 -0700 Subject: [PATCH 07/20] Parameter names/ordering Signed-off-by: steve lasker --- .../create_hashed_signed_statement.py | 22 ++++++------ scitt-scripts/entrypoint.sh | 35 ++++++++++--------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index dd2d8d6..9b7fe5a 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -63,12 +63,12 @@ def open_payload(payload_file: str) -> str: def create_hashed_signed_statement( - signing_key: SigningKey, + content_type: str, + issuer: str, payload: str, + payload_location: str, + signing_key: SigningKey, subject: str, - issuer: str, - content_type: str, - location: str, ) -> bytes: """ creates a hashed signed statement, given the signing_key, payload, subject and issuer @@ -200,17 +200,17 @@ def main(): payload = open_payload(args.payload_file) signed_statement = create_hashed_signed_statement( - signing_key_file, - payload, - args.payload_location, - args.subject, - args.issuer, - args.content_type, + content_type=args.content_type, + issuer=args.issuer, + payload=payload, + payload_location=args.payload_location, + signing_key=signing_key, + subject=args.subject ) with open(args.output_file, "wb") as output_file: output_file.write(signed_statement) - +s if __name__ == "__main__": main() diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 3b95369..99d6e68 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -5,25 +5,25 @@ # echo "datatrails-client_id: " ${2} # echo "datatrails-secret: " ${3} # echo "issuer: " ${4} -# echo "subject: " ${5} -# echo "payload_file: " ${6} -# echo "payload-location: " ${7} -# echo "receipt-file: " ${8} -# echo "signed-statement-file: " ${9} -# echo "signing-key-file: " ${10} -# echo "skip-receipt: " ${11} +# echo "payload-file: " ${5} +# echo "payload-location: " ${6} +# echo "receipt-file: " ${7} +# echo "signed-statement-file: " ${8} +# echo "signing-key-file: " ${9} +# echo "skip-receipt: " ${10} +# echo "subject: " ${11} CONTENT_TYPE=${1} DATATRAILS_CLIENT_ID=${2} DATATRAILS_SECRET_ID=${3} ISSUER=${4} -SUBJECT=${5} -PAYLOAD=${6} -PAYLOAD_LOCATION=${7} -RECEIPT_FILE=${8} -SIGNED_STATEMENT_FILE=${9} -SIGNING_KEY_FILE=${10} -SKIP_RECEIPT=${11} +PAYLOAD_FILE=${5} +PAYLOAD_LOCATION=${6} +RECEIPT_FILE=${7} +SIGNED_STATEMENT_FILE=${8} +SIGNING_KEY_FILE=${9} +SKIP_RECEIPT=${10} +SUBJECT=${11} TOKEN_FILE="./bearer-token.txt" @@ -37,12 +37,13 @@ echo "Create an access token" echo "Create a Signed Statement, hashing the payload" python /scripts/create_hashed_signed_statement.py \ - --subject $SUBJECT \ - --payload $PAYLOAD_FILE \ --content-type $CONTENT_TYPE \ + --issuer $ISSUER \ --output-file $SIGNED_STATEMENT_FILE \ + --payload-file $PAYLOAD_FILE \ + --payload-location $PAYLOAD_LOCATION \ --signing-key-file $SIGNING_KEY_FILE \ - --issuer $ISSUER + --subject $SUBJECT if [ ! -f $SIGNED_STATEMENT_FILE ]; then echo "ERROR: Signed Statement: [$SIGNED_STATEMENT_FILE] Not found!" From b6088b2d034b4cbfd7d9f5e3cf64770be492c03a Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 13:12:59 -0700 Subject: [PATCH 08/20] Parameter names/ordering Signed-off-by: steve lasker --- scitt-scripts/create_hashed_signed_statement.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index 9b7fe5a..e989067 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -197,12 +197,12 @@ def main(): args = parser.parse_args() signing_key = open_signing_key(args.signing_key_file) - payload = open_payload(args.payload_file) + payload_contents = open_payload(args.payload_file) signed_statement = create_hashed_signed_statement( content_type=args.content_type, issuer=args.issuer, - payload=payload, + payload=payload_contents, payload_location=args.payload_location, signing_key=signing_key, subject=args.subject @@ -210,7 +210,7 @@ def main(): with open(args.output_file, "wb") as output_file: output_file.write(signed_statement) -s + if __name__ == "__main__": main() From 171073c935368e79128f868c926d50efb71aa0af Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 13:30:57 -0700 Subject: [PATCH 09/20] parameter names/error handling Signed-off-by: steve lasker --- scitt-scripts/create_hashed_signed_statement.py | 2 +- scitt-scripts/entrypoint.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index e989067..4b23dfa 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -105,7 +105,7 @@ def create_hashed_signed_statement( }, }, HEADER_LABEL_PAYLOAD_HASH_ALGORITHM: -16, # for sha256 - HEADER_LABEL_LOCATION: location, + HEADER_LABEL_LOCATION: payload_location, } # now create a sha256 hash of the payload diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 99d6e68..3ecd59c 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -1,5 +1,7 @@ #!/bin/bash -l +set -e + # Uncomment for debugging # echo "content-type: " ${1} # echo "datatrails-client_id: " ${2} From 0a5d91ec58f614d3c099f5390b78c74f8ad2ef5e Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 13:36:11 -0700 Subject: [PATCH 10/20] test error handling Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 3ecd59c..cda257a 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -29,7 +29,6 @@ SUBJECT=${11} TOKEN_FILE="./bearer-token.txt" - echo "Create an access token" /scripts/create-token.sh ${DATATRAILS_CLIENT_ID} ${DATATRAILS_SECRET_ID} $TOKEN_FILE @@ -43,7 +42,7 @@ python /scripts/create_hashed_signed_statement.py \ --issuer $ISSUER \ --output-file $SIGNED_STATEMENT_FILE \ --payload-file $PAYLOAD_FILE \ - --payload-location $PAYLOAD_LOCATION \ + --location $PAYLOAD_LOCATION \ --signing-key-file $SIGNING_KEY_FILE \ --subject $SUBJECT From eda8c50c23f024b2d59593f469327f8f0f7cf605 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 15:00:43 -0700 Subject: [PATCH 11/20] test error handling Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index cda257a..b9a2fd0 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -42,7 +42,7 @@ python /scripts/create_hashed_signed_statement.py \ --issuer $ISSUER \ --output-file $SIGNED_STATEMENT_FILE \ --payload-file $PAYLOAD_FILE \ - --location $PAYLOAD_LOCATION \ + --payload-location $PAYLOAD_LOCATION \ --signing-key-file $SIGNING_KEY_FILE \ --subject $SUBJECT @@ -53,7 +53,7 @@ fi echo "Register the SCITT SIgned Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" -RESPONSE=$(curl -X POST -H @$TOKEN_FILE \ +RESPONSE=$(curl -X POST -H @$TOKEN_FILE_NIL \ --data-binary @$SIGNED_STATEMENT_FILE \ https://app.datatrails.ai/archivist/v1/publicscitt/entries) From 75d644feec0a8215d4e8fa18986348ddb7f44205 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 15:03:04 -0700 Subject: [PATCH 12/20] test error handling Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index b9a2fd0..f5519d5 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -53,7 +53,7 @@ fi echo "Register the SCITT SIgned Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" -RESPONSE=$(curl -X POST -H @$TOKEN_FILE_NIL \ +RESPONSE=$(curl -X POST \ --data-binary @$SIGNED_STATEMENT_FILE \ https://app.datatrails.ai/archivist/v1/publicscitt/entries) From ebb0dcb49f4c9fdf972ad90bc0b476caad059782 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 15:08:32 -0700 Subject: [PATCH 13/20] test error handling Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index f5519d5..49ac66b 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -51,7 +51,7 @@ if [ ! -f $SIGNED_STATEMENT_FILE ]; then return 404 fi -echo "Register the SCITT SIgned Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" +echo "Register the SCITT Signed Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" RESPONSE=$(curl -X POST \ --data-binary @$SIGNED_STATEMENT_FILE \ @@ -62,6 +62,10 @@ echo "RESPONSE: $RESPONSE" OPERATION_ID=$(echo $RESPONSE | jq -r .operationID) echo "OPERATION_ID: $OPERATION_ID" +if [ ${#OPERATION_ID} -lt -1 ] + return -1 +fi + echo "skip-receipt: $SKIP_RECEIPT" if [ -n "$SKIP_RECEIPT" ] && [ $SKIP_RECEIPT = "1" ]; then From 21fd56cbbe7066f8ce3080cdbb9fe66f4b2d1ef9 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 15:21:52 -0700 Subject: [PATCH 14/20] Complete error handling Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 49ac66b..81675f9 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -48,12 +48,12 @@ python /scripts/create_hashed_signed_statement.py \ if [ ! -f $SIGNED_STATEMENT_FILE ]; then echo "ERROR: Signed Statement: [$SIGNED_STATEMENT_FILE] Not found!" - return 404 + exit 126 fi echo "Register the SCITT Signed Statement to https://app.datatrails.ai/archivist/v1/publicscitt/entries" -RESPONSE=$(curl -X POST \ +RESPONSE=$(curl -X POST -H @$TOKEN_FILE \ --data-binary @$SIGNED_STATEMENT_FILE \ https://app.datatrails.ai/archivist/v1/publicscitt/entries) @@ -62,8 +62,11 @@ echo "RESPONSE: $RESPONSE" OPERATION_ID=$(echo $RESPONSE | jq -r .operationID) echo "OPERATION_ID: $OPERATION_ID" -if [ ${#OPERATION_ID} -lt -1 ] - return -1 +if [ ${#OPERATION_ID} -lt 1 ]; then + echo "error: OPERATION_ID not found. POST to https://app.datatrails.ai/archivist/v1/publicscitt/entries failed" + exit 126 +else + exit 0 fi echo "skip-receipt: $SKIP_RECEIPT" @@ -73,10 +76,14 @@ if [ -n "$SKIP_RECEIPT" ] && [ $SKIP_RECEIPT = "1" ]; then else echo "Download the SCITT Receipt: $RECEIPT_FILE" echo "call: /scripts/check_operation_status.py" - python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE - ENTRY_ID=$(python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE) echo "ENTRY_ID :" $ENTRY_ID + + if [ ${#ENTRY_ID} -lt 1 ]; then + echo "error: ENTRY_ID not found. check_operation_status.py failed" + exit 126 + fi + curl -H @$TOKEN_FILE \ https://app.datatrails.ai/archivist/v1/publicscitt/entries/$ENTRY_ID/receipt \ -o $RECEIPT_FILE From ac50ead2dd8448c4310e86d394b3123b8351a5dd Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 16:43:23 -0700 Subject: [PATCH 15/20] Add COSE Type for hashed payloads Signed-off-by: steve lasker --- scitt-scripts/create_signed_statement.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scitt-scripts/create_signed_statement.py b/scitt-scripts/create_signed_statement.py index 2d42a40..61ded81 100755 --- a/scitt-scripts/create_signed_statement.py +++ b/scitt-scripts/create_signed_statement.py @@ -36,6 +36,10 @@ HEADER_LABEL_CWT_CNF = 8 HEADER_LABEL_CNF_COSE_KEY = 1 +# CBOR Object Signing and Encryption (COSE) "typ" (type) Header Parameter +# https://datatracker.ietf.org/doc/rfc9596/ +HEADER_LABEL_TYPE = 16 +COSE_TYPE="application/hashed+cose" def open_signing_key(key_file: str) -> SigningKey: """ @@ -86,6 +90,7 @@ def create_signed_statement( # create a protected header where # the verification key is attached to the cwt claims protected_header = { + HEADER_LABEL_TYPE: COSE_TYPE, Algorithm: Es256, KID: b"testkey", ContentType: content_type, From 4428843af67741ddc17f9d16f2ded597fb023069 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 16:46:53 -0700 Subject: [PATCH 16/20] Cleanup feed, add COSE TYPE Signed-off-by: steve lasker --- scitt-scripts/create_hashed_signed_statement.py | 5 +++++ scitt-scripts/create_signed_statement.py | 12 ------------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/scitt-scripts/create_hashed_signed_statement.py b/scitt-scripts/create_hashed_signed_statement.py index 4b23dfa..7f47b34 100644 --- a/scitt-scripts/create_hashed_signed_statement.py +++ b/scitt-scripts/create_hashed_signed_statement.py @@ -41,6 +41,10 @@ HEADER_LABEL_PAYLOAD_HASH_ALGORITHM = -6800 HEADER_LABEL_LOCATION = -6801 +# CBOR Object Signing and Encryption (COSE) "typ" (type) Header Parameter +# https://datatracker.ietf.org/doc/rfc9596/ +HEADER_LABEL_TYPE = 16 +COSE_TYPE="application/hashed+cose" def open_signing_key(key_file: str) -> SigningKey: """ @@ -89,6 +93,7 @@ def create_hashed_signed_statement( # create a protected header where # the verification key is attached to the cwt claims protected_header = { + HEADER_LABEL_TYPE: COSE_TYPE, Algorithm: Es256, KID: b"testkey", ContentType: content_type, diff --git a/scitt-scripts/create_signed_statement.py b/scitt-scripts/create_signed_statement.py index 61ded81..88ff96a 100755 --- a/scitt-scripts/create_signed_statement.py +++ b/scitt-scripts/create_signed_statement.py @@ -17,11 +17,6 @@ from ecdsa import SigningKey, VerifyingKey - -# subject header label comes from version 2 of the scitt architecture document -# https://www.ietf.org/archive/id/draft-birkholz-scitt-architecture-02.html#name-envelope-and-claim-format -HEADER_LABEL_FEED = 392 - # CWT header label comes from version 4 of the scitt architecture document # https://www.ietf.org/archive/id/draft-ietf-scitt-architecture-04.html#name-issuer-identity HEADER_LABEL_CWT = 13 @@ -36,11 +31,6 @@ HEADER_LABEL_CWT_CNF = 8 HEADER_LABEL_CNF_COSE_KEY = 1 -# CBOR Object Signing and Encryption (COSE) "typ" (type) Header Parameter -# https://datatracker.ietf.org/doc/rfc9596/ -HEADER_LABEL_TYPE = 16 -COSE_TYPE="application/hashed+cose" - def open_signing_key(key_file: str) -> SigningKey: """ opens the signing key from the key file. @@ -90,11 +80,9 @@ def create_signed_statement( # create a protected header where # the verification key is attached to the cwt claims protected_header = { - HEADER_LABEL_TYPE: COSE_TYPE, Algorithm: Es256, KID: b"testkey", ContentType: content_type, - HEADER_LABEL_FEED: subject, HEADER_LABEL_CWT: { HEADER_LABEL_CWT_ISSUER: issuer, HEADER_LABEL_CWT_SUBJECT: subject, From 598168a773a3d8b1e35d4833941d42ea73a4b266 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Tue, 16 Jul 2024 16:54:51 -0700 Subject: [PATCH 17/20] Revert signed statement changes Signed-off-by: steve lasker --- scitt-scripts/create_signed_statement.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scitt-scripts/create_signed_statement.py b/scitt-scripts/create_signed_statement.py index 88ff96a..2d42a40 100755 --- a/scitt-scripts/create_signed_statement.py +++ b/scitt-scripts/create_signed_statement.py @@ -17,6 +17,11 @@ from ecdsa import SigningKey, VerifyingKey + +# subject header label comes from version 2 of the scitt architecture document +# https://www.ietf.org/archive/id/draft-birkholz-scitt-architecture-02.html#name-envelope-and-claim-format +HEADER_LABEL_FEED = 392 + # CWT header label comes from version 4 of the scitt architecture document # https://www.ietf.org/archive/id/draft-ietf-scitt-architecture-04.html#name-issuer-identity HEADER_LABEL_CWT = 13 @@ -31,6 +36,7 @@ HEADER_LABEL_CWT_CNF = 8 HEADER_LABEL_CNF_COSE_KEY = 1 + def open_signing_key(key_file: str) -> SigningKey: """ opens the signing key from the key file. @@ -83,6 +89,7 @@ def create_signed_statement( Algorithm: Es256, KID: b"testkey", ContentType: content_type, + HEADER_LABEL_FEED: subject, HEADER_LABEL_CWT: { HEADER_LABEL_CWT_ISSUER: issuer, HEADER_LABEL_CWT_SUBJECT: subject, From c858e7029e3ed6633fd6b0decf17728472a230ea Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 19 Jul 2024 10:21:54 -0700 Subject: [PATCH 18/20] Add more robustness to check-operation-status Signed-off-by: steve lasker --- scitt-scripts/check_operation_status.py | 67 +++++++++++++++---------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/scitt-scripts/check_operation_status.py b/scitt-scripts/check_operation_status.py index ac7a66b..2314d5a 100755 --- a/scitt-scripts/check_operation_status.py +++ b/scitt-scripts/check_operation_status.py @@ -2,6 +2,8 @@ import os import argparse +import logging +import sys from time import sleep as time_sleep @@ -10,7 +12,7 @@ # all timeouts and durations are in seconds REQUEST_TIMEOUT = 30 -POLL_TIMEOUT = 360 +POLL_TIMEOUT = 60 POLL_INTERVAL = 10 @@ -39,10 +41,7 @@ def get_operation_status(operation_id: str, headers: dict) -> dict: while True: response = requests.get(url, timeout=30, headers=headers) - # print("***response:", flush=True) - # print(response, flush=True) - # print(response.json, flush=True) - # print("***response:", flush=True) + if response.status_code == 200: break elif response.status_code == 400: @@ -53,27 +52,35 @@ def get_operation_status(operation_id: str, headers: dict) -> dict: return response.json() -def poll_operation_status(operation_id: str, headers: dict) -> str: +def poll_operation_status( + operation_id: str, headers: dict, logger: logging.Logger +) -> str: """ polls for the operation status to be 'succeeded'. """ poll_attempts: int = int(POLL_TIMEOUT / POLL_INTERVAL) - for _ in range(poll_attempts): - operation_status = get_operation_status(operation_id, headers) - # print("***operation_status:", flush=True) - # print(operation_status, flush=True) - # print("***operation_status:", flush=True) - - # pylint: disable=fixme - # TODO: ensure get_operation_status handles error cases from the rest request - if "status" in operation_status and operation_status["status"] == "succeeded": - return operation_status["entryID"] + logger.info("starting to poll for operation status 'succeeded'") + for _ in range(poll_attempts): + try: + operation_status = get_operation_status(operation_id, headers) + + # pylint: disable=fixme + # TODO: ensure get_operation_status handles error cases from the rest request + if ( + "status" in operation_status + and operation_status["status"] == "succeeded" + ): + return operation_status["entryID"] + + except requests.HTTPError as e: + logger.debug("failed getting operation status, error: %s", e) + time_sleep(POLL_INTERVAL) - raise TimeoutError("signed statement not registered within polling duration.") + raise TimeoutError("signed statement not registered within polling duration") def main(): @@ -108,21 +115,27 @@ def main(): default=default_token_file_name, ) + # log level + parser.add_argument( + "--log-level", + type=str, + help="log level. for any individual poll errors use DEBUG, defaults to WARNING", + default="WARNING", + ) + args = parser.parse_args() - # print("args.token_file_name:", flush=True) - # print(args.token_file_name, flush=True) + logger = logging.getLogger("check operation status") + logging.basicConfig(level=logging.getLevelName(args.log_level)) headers = get_token_from_file(args.token_file_name) - # print("headers:", flush=True) - # print(headers, flush=True) - - # print("operation_id:", flush=True) - # print(args.operation_id, flush=True) - - entry_id = poll_operation_status(args.operation_id, headers) - print(entry_id, flush=True) + try: + entry_id = poll_operation_status(args.operation_id, headers, logger) + print(entry_id) + except TimeoutError as e: + print(e, file=sys.stderr) + sys.exit(1) if __name__ == "__main__": main() From 4df9f9b08cdac3a1958e6aed0f398fd31bbeb554 Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 19 Jul 2024 10:31:42 -0700 Subject: [PATCH 19/20] Remove eronous return Signed-off-by: steve lasker --- scitt-scripts/entrypoint.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scitt-scripts/entrypoint.sh b/scitt-scripts/entrypoint.sh index 81675f9..7efff8b 100755 --- a/scitt-scripts/entrypoint.sh +++ b/scitt-scripts/entrypoint.sh @@ -65,8 +65,6 @@ echo "OPERATION_ID: $OPERATION_ID" if [ ${#OPERATION_ID} -lt 1 ]; then echo "error: OPERATION_ID not found. POST to https://app.datatrails.ai/archivist/v1/publicscitt/entries failed" exit 126 -else - exit 0 fi echo "skip-receipt: $SKIP_RECEIPT" @@ -77,8 +75,8 @@ else echo "Download the SCITT Receipt: $RECEIPT_FILE" echo "call: /scripts/check_operation_status.py" ENTRY_ID=$(python /scripts/check_operation_status.py --operation-id $OPERATION_ID --token-file-name $TOKEN_FILE) - echo "ENTRY_ID :" $ENTRY_ID + echo "ENTRY_ID :" $ENTRY_ID if [ ${#ENTRY_ID} -lt 1 ]; then echo "error: ENTRY_ID not found. check_operation_status.py failed" exit 126 From 9bc85c6f98e665a1e1fe74bcaa0b1538d58d4fad Mon Sep 17 00:00:00 2001 From: steve lasker Date: Fri, 19 Jul 2024 10:35:30 -0700 Subject: [PATCH 20/20] Add preview note Signed-off-by: steve lasker --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 657c3e5..6cf8844 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ Secure your Software Supply Chain and your Content Authenticity with immutable data trails. This GitHub Action uses DataTrails implementation of the IETF Supply Chain, Integrity and Trust ([SCITT](https://scitt.io)) APIs. +**NOTE:**: +This SCITT GitHub Action is in Preview, pending adoption of the [SCITT Reference APIs (SCRAPI)](https://datatracker.ietf.org/doc/draft-ietf-scitt-scrapi/). +To use a production supported implementation, please contact [DataTrails](https://www.datatrails.ai/contactus/) for more info. + ## Getting Started To create immutable data trails, an account with a `Client_ID` and `Secret` are required.