diff --git a/docs/transactions.md b/docs/transactions.md index 71b21d26e..5b5f1ca36 100644 --- a/docs/transactions.md +++ b/docs/transactions.md @@ -905,13 +905,17 @@ already present on the ledger. The certificate is immutable. It can only be revoked by either the owner or a quorum of Trustees. +- Who can send: Vendor account + - PAA (Root certificates) are VID-scoped: + - the vid field in the subject of the root certificate, as well as in the intermediate/leaf X509 certificates and the Vendor account's VID certificate, must be the same. + - Non-VID scoped PAAs (Root certificates): + - if the intermediate/leaf X509 certificate is VID-scoped, then the `vid` field in the certificate must match the corresponding PAA's `vid` field on the ledger, or the intermediate/leaf X509 certificate must not be VID-scoped. + - `vid` field associated with the corresponding PAA on the ledger must be equal to the Vendor account's VID. - Parameters: - cert: `string` - PEM encoded certificate. The corresponding CLI parameter can contain either a PEM string or a path to a file containing the data. - In State: - `pki/ApprovedCertificates/value//` - `pki/ChildCertificates/value//` -- Who can send: - - Any role - CLI command: - `dcld tx pki add-x509-cert --certificate= --from=` - Validation: @@ -921,7 +925,7 @@ The certificate is immutable. It can only be revoked by either the owner or a qu - no existing certificate with the same `:` combination. - if certificates with the same `:` combination already exist: - the existing certificate must not be NOC certificate - - sender must match to the owner of the existing certificates. + - the sender's VID must match the `vid` field of the existing certificates. - the signature (self-signature) and expiration date are valid. - parent certificate must be already stored on the ledger and a valid chain to some root certificate can be built. @@ -938,9 +942,10 @@ If a Revocation Distribution Point needs to be published (such as RFC5280 Certif If `revoke-child` flag is set to `true` then all the certificates in the chain signed by the revoked certificate will be revoked as well. -Only the owner (sender) can revoke the certificate. Root certificates can not be revoked this way, use `PROPOSE_X509_CERT_REVOC` and `APPROVE_X509_ROOT_CERT_REVOC` instead. +- Who can send: Vendor account + - the sender's VID must match the `vid` field of the revoking certificates. - Parameters: - subject: `string` - certificates's `Subject` is base64 encoded subject DER sequence bytes - subject_key_id: `string` - certificates's `Subject Key Id` in hex string format, e.g: `5A:88:0E:6C:36:53:D0:7F:B0:89:71:A3:F4:73:79:09:30:E6:2B:DB` @@ -949,8 +954,6 @@ Root certificates can not be revoked this way, use `PROPOSE_X509_CERT_REVOC` an - info: `optional(string)` - information/notes for the revocation - time: `optional(int64)` - revocation time (number of nanoseconds elapsed since January 1, 1970 UTC). CLI uses the current time for that field. - In State: `pki/RevokedCertificates/value//` -- Who can send: - - Any role; owner - CLI command: - `dcld tx pki revoke-x509-cert --subject= --subject-key-id= --from=` @@ -960,15 +963,14 @@ Root certificates can not be revoked this way, use `PROPOSE_X509_CERT_REVOC` an Removes the given X509 certificate (either intermediate or leaf) from approved and revoked certificates list. -Only the owner (sender) can remove the certificate. Root certificates can not be removed this way. +- Who can send: Vendor account + - the sender's VID must match the `vid` field of the removing certificates. - Parameters: - subject: `string` - certificates's `Subject` is base64 encoded subject DER sequence bytes - subject_key_id: `string` - certificates's `Subject Key Id` in hex string format, e.g: `5A:88:0E:6C:36:53:D0:7F:B0:89:71:A3:F4:73:79:09:30:E6:2B:DB` - serial-number: `optional(string)` - certificate's serial number -- Who can send: - - Any role; owner - CLI command: - `dcld tx pki remove-x509-cert --subject= --subject-key-id= --from=` @@ -1041,7 +1043,6 @@ Publishing the revocation distribution endpoint doesn't automatically remove PAI and DACs (leaf certificates) added to DCL if they are revoked in the CRL identified by this distribution point. [REVOKE_X509_CERT](#revoke_x509_cert) needs to be called to remove an intermediate or leaf certificate from the ledger. - - Who can send: Vendor account - `vid` field in the transaction (`VendorID`) must be equal to the Vendor account's VID - VID-scoped PAAs (Root certs) and PAIs (Intermediate certs): `vid` field in the `CRLSignerCertificate`'s subject must be equal to the Vendor account's VID @@ -1140,7 +1141,7 @@ This transaction adds a NOC root certificate owned by the Vendor. - no existing certificate with the same `:` combination. - if certificates with the same `:` combination already exist: - the existing certificate must be NOC root certificate - - the sender's VID must match the vid field of the existing certificates. + - the sender's VID must match the `vid` field of the existing certificates. - the signature (self-signature) and expiration date must be valid. - Parameters: - cert: `string` - The NOC Root Certificate, encoded in X.509v3 PEM format. Can be a PEM string or a file path. diff --git a/integration_tests/cli/pki-add-vendor-x509-certificates.sh b/integration_tests/cli/pki-add-vendor-x509-certificates.sh index d7c12bb3f..1903a7cb2 100755 --- a/integration_tests/cli/pki-add-vendor-x509-certificates.sh +++ b/integration_tests/cli/pki-add-vendor-x509-certificates.sh @@ -5,13 +5,15 @@ root_cert_with_vid_65521_subject="MIGYMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcm root_cert_with_vid_65521_subject_key_id="CE:A8:92:66:EA:E0:80:BD:2B:B5:68:E4:0B:07:C4:FA:2C:34:6D:31" root_cert_with_vid_65521_path="integration_tests/constants/root_cert_with_vid" root_cert_with_vid_65521_vid=65521 -intermediate_cert_with_vid_subject="MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" -intermediate_cert_with_vid_subject_key_id="0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" + +intermediate_cert_with_vid_65521_subject="MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" +intermediate_cert_with_vid_65521_subject_key_id="0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" intermediate_cert_with_vid_65521_path="integration_tests/constants/intermediate_cert_with_vid_1" -intermediate_cert_with_vid_65522_path="integration_tests/constants/intermediate_cert_with_vid_2" intermediate_cert_with_vid_65521_serial_number="3" -intermediate_cert_with_vid_65522_serial_number="4" intermediate_cert_with_vid_65521_vid=65521 + +intermediate_cert_with_vid_65522_path="integration_tests/constants/intermediate_cert_with_vid_2" +intermediate_cert_with_vid_65522_serial_number="4" intermediate_cert_with_vid_65522_vid=65522 trustee_account="jack" @@ -32,6 +34,10 @@ check_response "$result" "\"code\": 0" result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject="$root_cert_with_vid_65521_subject" --subject-key-id="$root_cert_with_vid_65521_subject_key_id" --from $second_trustee_account --yes) check_response "$result" "\"code\": 0" +echo "Try to add the intermediate certificate using an account that does not have vendor role" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_with_vid_65521_path" --from $trustee_account --yes) +check_response "$result" "\"code\": 4" + echo "Add an intermediate certificate with vid=$intermediate_cert_with_vid_65521_vid by $vendor_account_65521 with vid=$vendor_vid_65521" result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_with_vid_65521_path" --from $vendor_account_65521 --yes) check_response "$result" "\"code\": 0" @@ -41,8 +47,8 @@ result=$(dcld query pki all-x509-certs) echo $result | jq check_response "$result" "\"subject\": \"$root_cert_with_vid_65521_subject\"" check_response "$result" "\"subjectKeyId\": \"$root_cert_with_vid_65521_subject_key_id\"" -check_response "$result" "\"subject\": \"$intermediate_cert_with_vid_subject\"" -check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_with_vid_subject_key_id\"" +check_response "$result" "\"subject\": \"$intermediate_cert_with_vid_65521_subject\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_with_vid_65521_subject_key_id\"" check_response "$result" "\"serialNumber\": \"$intermediate_cert_with_vid_65521_serial_number\"" echo "Try to add an intermediate certificate with vid=$intermediate_cert_with_vid_65522_vid by $vendor_account_65521 with vid=$vendor_vid_65521" @@ -53,15 +59,16 @@ echo "Request all approved root certificates should not contain intermediate cer result=$(dcld query pki all-x509-certs) echo $result | jq check_response "$result" "\"subject\": \"$root_cert_with_vid_65521_subject\"" -check_response "$result" "\"subject\": \"$intermediate_cert_with_vid_subject\"" +check_response "$result" "\"subject\": \"$intermediate_cert_with_vid_65521_subject\"" check_response "$result" "\"subjectKeyId\": \"$root_cert_with_vid_65521_subject_key_id\"" -check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_with_vid_subject_key_id\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_with_vid_65521_subject_key_id\"" check_response "$result" "\"serialNumber\": \"$intermediate_cert_with_vid_65521_serial_number\"" response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_with_vid_65522_serial_number\"" root_cert_with_no_vid_path="integration_tests/constants/paa_cert_no_vid" root_cert_with_no_vid_subject="MBoxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQQ==" root_cert_with_no_vid_subject_key_id="78:5C:E7:05:B8:6B:8F:4E:6F:C7:93:AA:60:CB:43:EA:69:68:82:D5" + intermediate_cert_with_vid_65522_path="integration_tests/constants/pai_cert_numeric_vid" intermediate_cert_with_vid_65522_subject="MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjI=" intermediate_cert_with_vid_65522_subject_key_id="61:3D:D0:87:35:5E:F0:8B:AE:01:E4:C6:9A:8F:C7:3D:AC:8C:7D:FD" @@ -111,3 +118,66 @@ check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_with_vid_65522_ check_response "$result" "\"serialNumber\": \"$intermediate_cert_with_vid_65522_serial_number\"" test_divider + +root_cert_subject="MIGCMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbQ==" +root_cert_subject_key_id="33:5E:0C:07:44:F8:B5:9C:CD:55:01:9B:6D:71:23:83:6F:D0:D4:BE" +root_cert_path="integration_tests/constants/root_with_same_subject_and_skid_1" +root_cert_serial_number="1" + +intermediate_cert_subject="MEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQ=" +intermediate_cert_subject_key_id="2E:13:3B:44:52:2C:30:E9:EC:FB:45:FA:5D:E5:04:0A:C1:C6:E6:B9" +intermediate_cert_1_path="integration_tests/constants/intermediate_with_same_subject_and_skid_1" +intermediate_cert_1_serial_number="3" +intermediate_cert_2_path="integration_tests/constants/intermediate_with_same_subject_and_skid_2" +intermediate_cert_2_serial_number="4" + +echo "Propose and approve root certificate" +result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_cert_path" --vid "$vendor_vid_65521" --from $trustee_account --yes) +check_response "$result" "\"code\": 0" +result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject="$root_cert_subject" --subject-key-id="$root_cert_subject_key_id" --from $second_trustee_account --yes) +check_response "$result" "\"code\": 0" + +echo "Add first intermediate certificate by $vendor_account_65521" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account_65521 --yes) +check_response "$result" "\"code\": 0" + +echo "Request all approved root certificates." +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" + +echo "Try to add second intermediate certificate with same subject and SKID by $vendor_account_65523" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account_65523 --yes) +check_response "$result" "\"code\": 4" + +echo "Request all approved root certificates should not contain intermediate cert with serialNumber=$intermediate_cert_2_serial_number" +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" +response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number\"" + +second_vendor_account_65521=second_vendor_account_$vendor_vid_65521 +echo "Create Vendor account - $second_vendor_account_65521" +create_new_vendor_account $second_vendor_account_65521 $vendor_vid_65521 + +echo "Add second intermediate certificate with same subject and SKID by $second_vendor_account_65521" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account_65521 --yes) +check_response "$result" "\"code\": 0" + +echo "Request all approved root certificates should contain intermediate cert with serialNumber=$intermediate_cert_2_serial_number" +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number\"" diff --git a/integration_tests/cli/pki-demo.sh b/integration_tests/cli/pki-demo.sh index 4798f7043..ec0d2b231 100755 --- a/integration_tests/cli/pki-demo.sh +++ b/integration_tests/cli/pki-demo.sh @@ -43,6 +43,14 @@ trustee_account_address=$(echo $passphrase | dcld keys show jack -a) second_trustee_account_address=$(echo $passphrase | dcld keys show alice -a) third_trustee_account_address=$(echo $passphrase | dcld keys show bob -a) +vendor_account=vendor_account_$vid +echo "Create Vendor account - $vendor_account" +create_new_vendor_account $vendor_account $vid + +vendor_account_65522=vendor_account_65522 +echo "Create Vendor account - $vendor_account_65522" +create_new_vendor_account $vendor_account_65522 65522 + echo "Create regular account" create_new_account user_account "CertificationCenter" test_divider @@ -374,9 +382,9 @@ echo "4. ADD INTERMEDIATE CERT" test_divider -echo "$user_account (Not Trustee) adds Intermediate certificate" +echo "$vendor_account adds Intermediate certificate" intermediate_path="integration_tests/constants/intermediate_cert" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $user_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" @@ -442,9 +450,9 @@ test_divider echo "5. ADD LEAF CERT" test_divider -echo "$trustee_account (Trustee) add Leaf certificate" +echo "$vendor_account add Leaf certificate" leaf_path="integration_tests/constants/leaf_cert" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" test_divider @@ -650,8 +658,16 @@ test_divider echo "6. REVOKE INTERMEDIATE (AND HENCE LEAF) CERTS - No Approvals needed" test_divider -echo "$user_account (Not Trustee) revokes only Intermediate certificate. This must not revoke its child - Leaf certificate." +echo "Try to revoke the intermediate certificate when sender is not Vendor account" result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$user_account --yes) +check_response "$result" "\"code\": 4" + +echo "Try to revoke the intermediate certificate using a vendor account with other VID" +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$vendor_account_65522 --yes) +check_response "$result" "\"code\": 4" + +echo "$vendor_account (Not Trustee) revokes only Intermediate certificate. This must not revoke its child - Leaf certificate." +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider diff --git a/integration_tests/cli/pki-remove-x509-certificates.sh b/integration_tests/cli/pki-remove-x509-certificates.sh index 3206ab46c..f7024e38d 100755 --- a/integration_tests/cli/pki-remove-x509-certificates.sh +++ b/integration_tests/cli/pki-remove-x509-certificates.sh @@ -24,6 +24,14 @@ test_divider echo "REMOVE X509 CERTIFICATES" +vendor_account_65521=vendor_account_$root_cert_vid +echo "Create Vendor account - $vendor_account_65521" +create_new_vendor_account $vendor_account_65521 $root_cert_vid + +vendor_account_65522=vendor_account_65522 +echo "Create Vendor account - $vendor_account_65522" +create_new_vendor_account $vendor_account_65522 65522 + echo "Propose and approve root certificate 1" result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_cert_1_path" --vid "$root_cert_vid" --from $trustee_account --yes) check_response "$result" "\"code\": 0" @@ -31,15 +39,15 @@ result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject=" check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 4" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Add a leaf certificate with serialNumber 5" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Request all approved root certificates." @@ -56,7 +64,7 @@ check_response "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number check_response "$result" "\"serialNumber\": \"$leaf_cert_serial_number\"" echo "Revoke an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Request all revoked certificates should contain only one intermediate certificate with serialNumber 3" @@ -68,11 +76,19 @@ check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number\"" echo "Remove intermediate certificate with invalid serialNumber" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="invalid" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="invalid" --from=$vendor_account_65521 --yes) check_response "$result" "\"code\": 404" -echo "Remove intermediate certificate with serialNumber 3" +echo "Try to remove the intermediate certificate when sender is not Vendor account" result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$trustee_account --yes) +check_response "$result" "\"code\": 4" + +echo "Try to remove the intermediate certificate using a vendor account with other VID" +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$vendor_account_65522 --yes) +check_response "$result" "\"code\": 4" + +echo "Remove intermediate certificate with serialNumber 3" +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Request all certificates should not contain intermediate certificate with serialNumber 3" @@ -97,7 +113,7 @@ check_response "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" echo "Remove an intermediate certificate with subject and subjectKeyId" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Request approved certificates by an intermediate certificate's subject and subjectKeyId should be empty" @@ -130,7 +146,7 @@ response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_se response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" echo "Remove leaf certificate" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$vendor_account_65521 --yes) check_response "$result" "\"code\": 0" echo "Request approved leaf certificates should be empty" diff --git a/integration_tests/cli/pki-revocation-with-revoking-child.sh b/integration_tests/cli/pki-revocation-with-revoking-child.sh index e1b1ed673..5a816b200 100755 --- a/integration_tests/cli/pki-revocation-with-revoking-child.sh +++ b/integration_tests/cli/pki-revocation-with-revoking-child.sh @@ -26,6 +26,10 @@ test_divider echo "REVOKE CERTIFICATES BY SPECIFYING SERIAL NUMBER" +vendor_account=vendor_account_$root_cert_vid +echo "Create Vendor account - $vendor_account" +create_new_vendor_account $vendor_account $root_cert_vid + echo "Propose and approve root certificate 1" result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_cert_1_path" --vid "$root_cert_vid" --from $trustee_account --yes) check_response "$result" "\"code\": 0" @@ -39,15 +43,15 @@ result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject=" check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 4" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add a leaf certificate with serialNumber 5" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all approved root certificates." @@ -60,7 +64,7 @@ check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\ check_response "$result" "\"subjectKeyId\": \"$leaf_cert_subject_key_id\"" echo "Revoke intermediate certificates and its child certificates too" -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --revoke-child=true --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --revoke-child=true --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all revoked certificates should contain two intermediate and one leaf certificates" @@ -88,21 +92,21 @@ response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_se response_does_not_contain "$result" "\"serialNumber\": \"$leaf_cert_serial_number" echo "Remove intermediate and leaf certificates to re-add them again" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 4" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add a leaf certificate with serialNumber 5" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "$trustee_account (Trustee) proposes to revoke Root certificates and its child certificates too" diff --git a/integration_tests/cli/pki-revocation-with-serial-number.sh b/integration_tests/cli/pki-revocation-with-serial-number.sh index 6eed1f244..243666ece 100755 --- a/integration_tests/cli/pki-revocation-with-serial-number.sh +++ b/integration_tests/cli/pki-revocation-with-serial-number.sh @@ -26,6 +26,10 @@ test_divider echo "REVOKE CERTIFICATES BY SPECIFYING SERIAL NUMBER" +vendor_account=vendor_account_$root_cert_vid +echo "Create Vendor account - $vendor_account" +create_new_vendor_account $vendor_account $root_cert_vid + echo "Propose and approve root certificate 1" result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_cert_1_path" --vid "$root_cert_vid" --from $trustee_account --yes) check_response "$result" "\"code\": 0" @@ -39,15 +43,15 @@ result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject=" check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 4" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add a leaf certificate with serialNumber 5" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all approved root certificates." @@ -65,11 +69,11 @@ check_response "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number check_response "$result" "\"serialNumber\": \"$leaf_cert_serial_number\"" echo "Revoke intermediate certificate with invalid serialNumber" -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="invalid" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="invalid" --from=$vendor_account --yes) check_response "$result" "\"code\": 404" echo "Revoke intermediate certificate with serialNumber 3 only(child certificates should not be removed)" -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_1_serial_number" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all revoked certificates should contain one intermediate certificate with serialNumber 3" @@ -97,7 +101,7 @@ check_response "$result" "\"subjectKeyId\": \"$leaf_cert_subject_key_id\"" check_response "$result" "\"serialNumber\": \"$leaf_cert_serial_number\"" echo "Revoke intermediate certificate with serialNumber 4 and its child certificates too" -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_2_serial_number" --revoke-child=true --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --serial-number="$intermediate_cert_2_serial_number" --revoke-child=true --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all revoked certificates should contain two intermediate and one leaf certificates" @@ -125,21 +129,21 @@ response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_se response_does_not_contain "$result" "\"serialNumber\": \"$leaf_cert_serial_number" echo "Remove intermediate and leaf certificates to re-add them again" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$intermediate_cert_subject" --subject-key-id="$intermediate_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" -result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki remove-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 3" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add an intermediate certificate with serialNumber 4" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Add a leaf certificate with serialNumber 5" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_cert_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "Request all approved root certificates." diff --git a/integration_tests/constants/constants.go b/integration_tests/constants/constants.go index b494f8c33..df67bac6c 100644 --- a/integration_tests/constants/constants.go +++ b/integration_tests/constants/constants.go @@ -655,10 +655,12 @@ M6mDL6NurBAW1pJlg8OT RootCertWithVidSubjectKeyID = "CE:A8:92:66:EA:E0:80:BD:2B:B5:68:E4:0B:07:C4:FA:2C:34:6D:31" RootCertWithVidVid = 65521 - IntermediateCertWithVidSubject = "MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" - IntermediateCertWithVidSubjectKeyID = "0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" + IntermediateCertWithVid1Subject = "MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" + IntermediateCertWithVid1SubjectKeyID = "0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" IntermediateCertWithVid1SerialNumber = "3" - IntermediateCertWithVid2SerialNumber = "4" IntermediateCertWithVid1Vid = 65521 + + IntermediateCertWithVid2SubjectKeyID = "0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" + IntermediateCertWithVid2SerialNumber = "4" IntermediateCertWithVid2Vid = 65522 ) diff --git a/integration_tests/grpc_rest/pki/helpers.go b/integration_tests/grpc_rest/pki/helpers.go index f895aaf62..dc5c07cea 100644 --- a/integration_tests/grpc_rest/pki/helpers.go +++ b/integration_tests/grpc_rest/pki/helpers.go @@ -21,7 +21,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" - tmrand "github.com/tendermint/tendermint/libs/rand" testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" test_dclauth "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/grpc_rest/dclauth" "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/utils" @@ -650,13 +649,12 @@ func Demo(suite *utils.TestSuite) { require.NoError(suite.T, err) // Register new Vendor account - vid := int32(tmrand.Uint16()) vendorName := utils.RandString() vendorAccount := test_dclauth.CreateVendorAccount( suite, vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, - vid, + testconstants.Vid, testconstants.ProductIDsEmpty, aliceName, aliceAccount, @@ -784,8 +782,16 @@ func Demo(suite *utils.TestSuite) { require.Equal(suite.T, jackAccount.Address, certificate.Certs[0].Owner) require.True(suite.T, certificate.Certs[0].IsRoot) - // User (Not Trustee) add Intermediate certificate + // Try to add Intermediate certificate when sender is not Vendor account msgAddX509Cert := pkitypes.MsgAddX509Cert{ + Cert: testconstants.IntermediateCertPem, + Signer: aliceAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + require.Error(suite.T, err) + + // Vandor add Intermediate certificate + msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateCertPem, Signer: vendorAccount.Address, } @@ -822,12 +828,12 @@ func Demo(suite *utils.TestSuite) { require.Equal(suite.T, vendorAccount.Address, certificate.Certs[0].Owner) require.False(suite.T, certificate.Certs[0].IsRoot) - // Alice (Trustee) add Leaf certificate + // Vandor add Leaf certificate secondMsgAddX509Cert := pkitypes.MsgAddX509Cert{ Cert: testconstants.LeafCertPem, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&secondMsgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&secondMsgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Request all proposed Root certificates @@ -859,7 +865,7 @@ func Demo(suite *utils.TestSuite) { require.Equal(suite.T, testconstants.LeafSubjectKeyID, certificate.SubjectKeyId) require.Equal(suite.T, 1, len(certificate.Certs)) require.Equal(suite.T, testconstants.LeafCertPem, certificate.Certs[0].PemCert) - require.Equal(suite.T, aliceAccount.Address, certificate.Certs[0].Owner) + require.Equal(suite.T, vendorAccount.Address, certificate.Certs[0].Owner) require.Equal(suite.T, testconstants.LeafSubject, certificate.Certs[0].Subject) require.Equal(suite.T, testconstants.LeafSubjectKeyID, certificate.Certs[0].SubjectKeyId) require.Equal(suite.T, testconstants.LeafSubjectAsText, certificate.Certs[0].SubjectAsText) @@ -910,8 +916,18 @@ func Demo(suite *utils.TestSuite) { _, err = GetAllChildX509Certs(suite, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) suite.AssertNotFound(err) - // User (Not Trustee) revokes Intermediate certificate. With `RevokeChild` set to true, its child must also be revoked - Leaf certificate. + // Try to Revoke Intermediate certificate when sender is not Vendor account msgRevokeX509Cert := pkitypes.MsgRevokeX509Cert{ + Subject: testconstants.IntermediateSubject, + SubjectKeyId: testconstants.IntermediateSubjectKeyID, + RevokeChild: true, + Signer: aliceAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRevokeX509Cert}, aliceName, aliceAccount) + require.Error(suite.T, err) + + // Vendor revokes Intermediate certificate. With `RevokeChild` set to true, its child must also be revoked - Leaf certificate. + msgRevokeX509Cert = pkitypes.MsgRevokeX509Cert{ Subject: testconstants.IntermediateSubject, SubjectKeyId: testconstants.IntermediateSubjectKeyID, RevokeChild: true, @@ -958,7 +974,7 @@ func Demo(suite *utils.TestSuite) { require.Equal(suite.T, testconstants.LeafSubject, revokedCertificate.Certs[0].Subject) require.Equal(suite.T, testconstants.LeafSubjectKeyID, revokedCertificate.Certs[0].SubjectKeyId) require.Equal(suite.T, testconstants.LeafCertPem, revokedCertificate.Certs[0].PemCert) - require.Equal(suite.T, aliceAccount.Address, revokedCertificate.Certs[0].Owner) + require.Equal(suite.T, vendorAccount.Address, revokedCertificate.Certs[0].Owner) require.Equal(suite.T, testconstants.LeafSubjectAsText, revokedCertificate.Certs[0].SubjectAsText) require.False(suite.T, revokedCertificate.Certs[0].IsRoot) @@ -1701,23 +1717,31 @@ func Demo(suite *utils.TestSuite) { // Add intermediate and leaf certificates msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateWithSameSubjectAndSKID1, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) + // Try to add second intermediate certificate with same subject and SKID by another Vendor msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateWithSameSubjectAndSKID2, - Signer: aliceAccount.Address, + Signer: venAcc65522.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, venName65522, venAcc65522) + require.Error(suite.T, err) + + msgAddX509Cert = pkitypes.MsgAddX509Cert{ + Cert: testconstants.IntermediateWithSameSubjectAndSKID2, + Signer: vendorAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.LeafCertWithSameSubjectAndSKID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Check approved certificate @@ -1733,14 +1757,14 @@ func Demo(suite *utils.TestSuite) { Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, SerialNumber: "invalid", - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRevokeX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRevokeX509Cert}, vendorName, vendorAccount) require.Error(suite.T, err) // Revoke intermediate certificate with serialNumber 1 only(child certs should not be removed) msgRevokeX509Cert.SerialNumber = testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRevokeX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRevokeX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Request revoked certificate with serialNumber 3 @@ -1810,6 +1834,16 @@ func Demo(suite *utils.TestSuite) { // Remove x509 certificate with invalid serialNumber msgRemoveX509Cert := pkitypes.MsgRemoveX509Cert{ + Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + SerialNumber: "invalid", + Signer: vendorAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) + require.Error(suite.T, err) + + // Try to Remove x509 certificate by subject and subject key id when sender is not Vendor account + msgRemoveX509Cert = pkitypes.MsgRemoveX509Cert{ Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, SerialNumber: "invalid", @@ -1822,9 +1856,9 @@ func Demo(suite *utils.TestSuite) { msgRemoveX509Cert = pkitypes.MsgRemoveX509Cert{ Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Check that two intermediate certificates removed _, err = GetRevokedX509Cert(suite, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) @@ -1836,9 +1870,9 @@ func Demo(suite *utils.TestSuite) { msgRemoveX509Cert = pkitypes.MsgRemoveX509Cert{ Subject: testconstants.LeafCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Check that leaf certificate removed _, err = GetX509Cert(suite, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) @@ -1848,23 +1882,23 @@ func Demo(suite *utils.TestSuite) { // Add intermediate certificates msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateWithSameSubjectAndSKID1, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateWithSameSubjectAndSKID2, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.LeafCertWithSameSubjectAndSKID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Remove x509 certificate by serial number @@ -1872,9 +1906,9 @@ func Demo(suite *utils.TestSuite) { Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, SerialNumber: testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Check that leaf and x509 with different serial number is not removed @@ -1890,9 +1924,9 @@ func Demo(suite *utils.TestSuite) { msgRemoveX509Cert = pkitypes.MsgRemoveX509Cert{ Subject: testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) _, err = GetX509Cert(suite, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) @@ -1905,9 +1939,9 @@ func Demo(suite *utils.TestSuite) { msgRemoveX509Cert = pkitypes.MsgRemoveX509Cert{ Subject: testconstants.LeafCertWithSameSubjectAndSKIDSubject, SubjectKeyId: testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgRemoveX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) _, err = GetX509Cert(suite, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) @@ -1917,16 +1951,16 @@ func Demo(suite *utils.TestSuite) { // Add intermediate and leaf certificates msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.IntermediateWithSameSubjectAndSKID1, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) msgAddX509Cert = pkitypes.MsgAddX509Cert{ Cert: testconstants.LeafCertWithSameSubjectAndSKID, - Signer: aliceAccount.Address, + Signer: vendorAccount.Address, } - _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, aliceName, aliceAccount) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) require.NoError(suite.T, err) // Check that certs are added @@ -2031,7 +2065,7 @@ func Demo(suite *utils.TestSuite) { // Check approved certificates certs, _ = GetX509Cert(suite, testconstants.RootCertWithVidSubject, testconstants.RootCertWithVidSubjectKeyID) require.Equal(suite.T, 1, len(certs.Certs)) - certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVidSubject, testconstants.IntermediateCertWithVidSubjectKeyID) + certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVid1Subject, testconstants.IntermediateCertWithVid1SubjectKeyID) require.Equal(suite.T, 1, len(certs.Certs)) // Check that if root cert is VID scoped and rootVID != CertVID then adding an intermediate cert should fail @@ -2044,7 +2078,7 @@ func Demo(suite *utils.TestSuite) { require.Error(suite.T, err) // Check there is only one approved intermediate certificate - certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVidSubject, testconstants.IntermediateCertWithVidSubjectKeyID) + certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVid1Subject, testconstants.IntermediateCertWithVid1SubjectKeyID) require.Equal(suite.T, 1, len(certs.Certs)) require.Equal(suite.T, testconstants.IntermediateCertWithVid1SerialNumber, certs.Certs[0].SerialNumber) diff --git a/integration_tests/light_client_proxy/pki.sh b/integration_tests/light_client_proxy/pki.sh old mode 100644 new mode 100755 index a83a8ba08..cb6f10156 --- a/integration_tests/light_client_proxy/pki.sh +++ b/integration_tests/light_client_proxy/pki.sh @@ -131,14 +131,15 @@ dcld config node tcp://localhost:26657 trustee_account="jack" second_trustee_account="alice" -echo "Create regular account" -create_new_account user_account "CertificationCenter" +vendor_account=vendor_account_$vid +echo "Create Vendor account - $vendor_account" +create_new_vendor_account $vendor_account $vid test_divider -echo "$user_account (Not Trustee) propose Root certificate" +echo "$vendor_account (Not Trustee) propose Root certificate" root_path="integration_tests/constants/root_cert" -result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_path" --vid $vid --from $user_account --yes) +result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_path" --vid $vid --from $vendor_account --yes) response_does_not_contain "$result" "\"code\": 0" echo "$result" @@ -159,24 +160,24 @@ echo "$result" test_divider -echo "$user_account (Not Trustee) add Intermediate certificate" +echo "$vendor_account (Vendor) add Intermediate certificate" intermediate_path="integration_tests/constants/intermediate_cert" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $user_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "$result" test_divider -echo "$trustee_account (Trustee) add Leaf certificate" +echo "$vendor_account (Vendor) add Leaf certificate" leaf_path="integration_tests/constants/leaf_cert" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_path" --from $trustee_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$leaf_path" --from $vendor_account --yes) check_response "$result" "\"code\": 0" echo "$result" test_divider -echo "$trustee_account (Trustee) revokes Leaf certificate." -result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$trustee_account --yes) +echo "$vendor_account (Vendor) revokes Leaf certificate." +result=$(echo "$passphrase" | dcld tx pki revoke-x509-cert --subject="$leaf_cert_subject" --subject-key-id="$leaf_cert_subject_key_id" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" echo "$result" @@ -312,7 +313,7 @@ echo "try to write via light client proxy" test_divider echo "Add cert" -result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $user_account --yes) +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_path" --from $vendor_account --yes) echo "$result" check_response "$result" "Write requests don't work with a Light Client Proxy" diff --git a/integration_tests/upgrade/test-upgrade-0.12-to-1.2.sh b/integration_tests/upgrade/test-upgrade-0.12-to-1.2.sh index ef9cd2dd7..a111aca12 100755 --- a/integration_tests/upgrade/test-upgrade-0.12-to-1.2.sh +++ b/integration_tests/upgrade/test-upgrade-0.12-to-1.2.sh @@ -1139,13 +1139,13 @@ check_response "$result" "\"code\": 0" test_divider echo "Add intermediate_cert" -result=$(echo $passphrase | $DCLD_BIN_NEW tx pki add-x509-cert --certificate="$intermediate_cert_path_new" --from=$trustee_account_1 --yes) +result=$(echo $passphrase | $DCLD_BIN_NEW tx pki add-x509-cert --certificate="$intermediate_cert_path_new" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider echo "Revoke intermediate_cert" -result=$(echo $passphrase | $DCLD_BIN_NEW tx pki revoke-x509-cert --subject="$intermediate_cert_subject_new" --subject-key-id="$intermediate_cert_subject_key_id_new" --from=$trustee_account_1 --yes) +result=$(echo $passphrase | $DCLD_BIN_NEW tx pki revoke-x509-cert --subject="$intermediate_cert_subject_new" --subject-key-id="$intermediate_cert_subject_key_id_new" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider diff --git a/integration_tests/upgrade/test-upgrade-1.2-to-1.3.sh b/integration_tests/upgrade/test-upgrade-1.2-to-1.3.sh index 326c33fd3..680dd4c6d 100755 --- a/integration_tests/upgrade/test-upgrade-1.2-to-1.3.sh +++ b/integration_tests/upgrade/test-upgrade-1.2-to-1.3.sh @@ -473,7 +473,7 @@ check_response "$result" "\"code\": 0" test_divider echo "Add intermediate_cert" -result=$(echo $passphrase | $DCLD_BIN_OLD tx pki add-x509-cert --certificate="$intermediate_cert_path" --from=$trustee_account_1 --yes) +result=$(echo $passphrase | $DCLD_BIN_OLD tx pki add-x509-cert --certificate="$intermediate_cert_path" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider @@ -1176,7 +1176,7 @@ check_response "$result" "\"code\": 0" test_divider echo "Add intermediate_cert" -result=$(echo $passphrase | $DCLD_BIN_NEW tx pki add-x509-cert --certificate="$intermediate_cert_path_new" --from=$trustee_account_1 --yes) +result=$(echo $passphrase | $DCLD_BIN_NEW tx pki add-x509-cert --certificate="$intermediate_cert_path_new" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider @@ -1188,7 +1188,7 @@ check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id_ test_divider echo "Revoke intermediate_cert" -result=$(echo $passphrase | $DCLD_BIN_NEW tx pki revoke-x509-cert --subject="$intermediate_cert_subject_new" --subject-key-id="$intermediate_cert_subject_key_id_new" --from=$trustee_account_1 --yes) +result=$(echo $passphrase | $DCLD_BIN_NEW tx pki revoke-x509-cert --subject="$intermediate_cert_subject_new" --subject-key-id="$intermediate_cert_subject_key_id_new" --from=$vendor_account --yes) check_response "$result" "\"code\": 0" test_divider diff --git a/types/pki/errors.go b/types/pki/errors.go index 553b0e881..bfaca2bee 100644 --- a/types/pki/errors.go +++ b/types/pki/errors.go @@ -47,7 +47,7 @@ var ( ErrCertificateVidNotEqualMsgVid = sdkerrors.Register(ModuleName, 436, "certificate's vid is not equal to the message vid") ErrMessageVidNotEqualRootCertVid = sdkerrors.Register(ModuleName, 437, "Message vid is not equal to ledger's root certificate vid") ErrCertNotChainedBack = sdkerrors.Register(ModuleName, 438, "Certificate is not chained back to a root certificate on DCL") - ErrCertVidNotEqualAccountVid = sdkerrors.Register(ModuleName, 439, "account's vid is not equal to ledger's certificate vid") + ErrCertVidNotEqualAccountVid = sdkerrors.Register(ModuleName, 439, "account's vid is not equal to certificate vid") ErrCertVidNotEqualToRootVid = sdkerrors.Register(ModuleName, 440, "certificate's vid is not equal to vid of root certificate ") ) @@ -183,11 +183,18 @@ func NewErrUnauthorizedCertIssuer(subject string, subjectKeyID string) error { func NewErrUnauthorizedCertOwner(subject string, subjectKeyID string) error { return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, - "Only owner of existing certificates with subject=%v and subjectKeyID=%v "+ - "can add new certificate with the same subject and subjectKeyID", + "Only the owner of certificates with subject=%v and subjectKeyID=%v has the authority "+ + "to add, remove, or revoke a certificate with the same subject and subjectKeyID", subject, subjectKeyID) } +func NewErrUnauthorizedCertVendor(ownerVid int32) error { + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, + "Only the vendor accounts with vid=%d, has the authority "+ + "to add, remove, or revoke a certificate with provided subject and subjectKeyID", + ownerVid) +} + func NewErrProvidedNocCertButExistingNotNoc(subject string, subjectKeyID string) error { return sdkerrors.Wrapf(ErrInappropriateCertificateType, "The existing certificate with the same combination of subject (%v) and subjectKeyID (%v) is not a NOC certificate", @@ -206,35 +213,24 @@ func NewErrProvidedNotNocCertButExistingNoc(subject string, subjectKeyID string) subject, subjectKeyID) } -func NewErrExistingCertVidNotEqualAccountVid(subject string, subjectKeyID string, vid int32) error { - return sdkerrors.Wrapf(ErrCertVidNotEqualAccountVid, - "Certificate with the same combination of subject=%v and subjectKeyID=%v "+ - "has already been published by another vendor with VID=%d.", - subject, subjectKeyID, vid) +func NewErrProvidedNotNocCertButRootIsNoc() error { + return sdkerrors.Wrapf(ErrInappropriateCertificateType, "The root is NOC certificate, but the provided certificate is not") } -func NewErrRootCertVidNotEqualToAccountVidOrCertVid(rootVID int32, accountVID int32, certVID int32) error { - if rootVID != certVID { - return sdkerrors.Wrapf(ErrCertVidNotEqualToRootVid, - "Root certificate is VID scoped: A child certificate must be also VID scoped to the same VID as a root one: "+ - "Root certificate's VID = %v, Certificate's VID = %v", - rootVID, certVID) - } +func NewErrRootCertVidNotEqualToCertVid(rootVID int32, certVID int32) error { + return sdkerrors.Wrapf(ErrCertVidNotEqualToRootVid, + "A child certificate must be also VID scoped to the same VID as a root one: "+ + "Root certificate's VID = %v, Child certificate's VID = %v", + rootVID, certVID) +} +func NewErrRootCertVidNotEqualToAccountVid(rootVID int32, accountVID int32) error { return sdkerrors.Wrapf(ErrCertVidNotEqualAccountVid, - "Root certificate is VID scoped: "+ - "Only a Vendor associated with this VID can add a child certificate: "+ + "Only a Vendor associated with VID of root certificate can add a child certificate: "+ "Root certificate's VID = %v, Account VID = %v", rootVID, accountVID) } -func NewErrAccountVidNotEqualToCertVid(accountVID int32, certVID int32) error { - return sdkerrors.Wrapf(ErrCertVidNotEqualAccountVid, - "Certificate is VID scoped: Only a vendor associated with this VID can add this certificate "+ - "Account VID = %v, Certificate's VID = %v", - accountVID, certVID) -} - func NewErrCRLSignerCertificatePidNotEqualMsgPid(certificatePid int32, messagePid int32) error { return sdkerrors.Wrapf( ErrCRLSignerCertificatePidNotEqualMsgPid, @@ -361,10 +357,6 @@ func NewErrMessageRemoveRoot(subject string, subjectKeyID string) error { ) } -func NewErrMessageOnlyOwnerCanExecute(command string) error { - return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "Only owner can revoke certificate using %s", command) -} - func NewErrUnsupportedOperation(e interface{}) error { return sdkerrors.Wrapf(ErrUnsupportedOperation, "%v", e) } diff --git a/x/pki/handler_add_noc_cert_test.go b/x/pki/handler_add_noc_cert_test.go index d83d667d0..9fcd1a763 100644 --- a/x/pki/handler_add_noc_cert_test.go +++ b/x/pki/handler_add_noc_cert_test.go @@ -19,8 +19,7 @@ func TestHandler_AddNocX509Cert_SenderNotVendor(t *testing.T) { addNocX509Cert := types.NewMsgAddNocX509Cert(setup.Trustee1.String(), testconstants.NocCert1) _, err := setup.Handler(setup.Ctx, addNocX509Cert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) } func TestHandler_AddNocX509Cert_AddNew(t *testing.T) { @@ -160,8 +159,7 @@ func TestHandler_AddNocX509Cert_Root_VID_Does_Not_Equal_To_AccountVID(t *testing // try to add NOC certificate nocX509Cert := types.NewMsgAddNocX509Cert(newAccAddress.String(), testconstants.NocCert1) _, err := setup.Handler(setup.Ctx, nocX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertVidNotEqualAccountVid.Is(err)) + require.ErrorIs(t, err, pkitypes.ErrCertVidNotEqualAccountVid) } func TestHandler_AddNocX509Cert_ForInvalidCertificate(t *testing.T) { @@ -174,8 +172,7 @@ func TestHandler_AddNocX509Cert_ForInvalidCertificate(t *testing.T) { // add x509 certificate addX509Cert := types.NewMsgAddNocX509Cert(accAddress.String(), testconstants.StubCertPem) _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInvalidCertificate.Is(err)) + require.ErrorIs(t, err, pkitypes.ErrInvalidCertificate) } func TestHandler_AddXNoc509Cert_ForNocRootCertificate(t *testing.T) { @@ -188,8 +185,7 @@ func TestHandler_AddXNoc509Cert_ForNocRootCertificate(t *testing.T) { // try to add root certificate x509 certificate addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.NocRootCert1) _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) + require.ErrorIs(t, err, pkitypes.ErrNonRootCertificateSelfSigned) } func TestHandler_AddXNoc509Cert_ForRootNonNocCertificate(t *testing.T) { @@ -212,7 +208,6 @@ func TestHandler_AddXNoc509Cert_ForRootNonNocCertificate(t *testing.T) { // try to add root certificate x509 certificate addX509Cert := types.NewMsgAddNocX509Cert(accAddress.String(), testconstants.IntermediateCertWithVid1) _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) require.ErrorIs(t, err, pkitypes.ErrInappropriateCertificateType) } @@ -333,7 +328,7 @@ func TestHandler_AddNocX509Cert_CertificateExist(t *testing.T) { Vid: testconstants.VendorID1, }, nocCert: testconstants.NocCert1, - err: pkitypes.ErrCertVidNotEqualAccountVid, + err: sdkerrors.ErrUnauthorized, }, } diff --git a/x/pki/handler_add_noc_root_cert_test.go b/x/pki/handler_add_noc_root_cert_test.go index 6c3b60431..75eebc910 100644 --- a/x/pki/handler_add_noc_root_cert_test.go +++ b/x/pki/handler_add_noc_root_cert_test.go @@ -133,7 +133,7 @@ func TestHandler_AddNocX509RootCert_CertificateExist(t *testing.T) { Vid: testconstants.VendorID1, }, nocRoorCert: testconstants.RootCertPem, - err: pkitypes.ErrCertVidNotEqualAccountVid, + err: sdkerrors.ErrUnauthorized, }, } diff --git a/x/pki/handler_add_non_root_cert_test.go b/x/pki/handler_add_non_root_cert_test.go new file mode 100644 index 000000000..34aeda65a --- /dev/null +++ b/x/pki/handler_add_non_root_cert_test.go @@ -0,0 +1,636 @@ +package pki + +import ( + "testing" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/require" + testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" + pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestHandler_AddX509Cert(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certificate, _ := querySingleApprovedCertificate( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, intermediateCertificate(accAddress), *certificate) + + certificateBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(certificateBySubjectKeyID)) + require.Equal(t, 1, len(certificateBySubjectKeyID[0].Certs)) + + certs := make([]*types.Certificate, 0) + certs = append(certs, certificate, certificateBySubjectKeyID[0].Certs[0]) + for _, cert := range certs { + // check + require.Equal(t, addX509Cert.Cert, cert.PemCert) + require.Equal(t, addX509Cert.Signer, cert.Owner) + require.Equal(t, testconstants.IntermediateSubject, cert.Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, cert.SubjectKeyId) + require.Equal(t, testconstants.IntermediateSerialNumber, cert.SerialNumber) + require.False(t, cert.IsRoot) + require.Equal(t, testconstants.IntermediateIssuer, cert.Issuer) + require.Equal(t, testconstants.IntermediateAuthorityKeyID, cert.AuthorityKeyId) + require.Equal(t, testconstants.RootSubject, cert.RootSubject) + require.Equal(t, testconstants.RootSubjectKeyID, cert.RootSubjectKeyId) + } + + // check that unique certificate key is registered + require.True(t, setup.Keeper.IsUniqueCertificatePresent( + setup.Ctx, testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) + + // check that child certificates of issuer contains certificate identifier + issuerChildren, _ := queryChildCertificates( + setup, testconstants.IntermediateIssuer, testconstants.IntermediateAuthorityKeyID) + require.Equal(t, 1, len(issuerChildren.CertIds)) + require.Equal(t, + &types.CertificateIdentifier{ + Subject: testconstants.IntermediateSubject, + SubjectKeyId: testconstants.IntermediateSubjectKeyID, + }, + issuerChildren.CertIds[0]) + + // check that no proposed certificate has been created + _, err = queryProposedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) +} + +func TestHandler_AddX509Cert_ForInvalidCertificate(t *testing.T) { + setup := Setup(t) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.StubCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInvalidCertificate) +} + +func TestHandler_AddX509Cert_ForRootCertificate(t *testing.T) { + setup := Setup(t) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1) + + // add root certificate as leaf x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.RootCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrNonRootCertificateSelfSigned) +} + +func TestHandler_AddX509Cert_ForDuplicate(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1) + + // store intermediate certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // store intermediate certificate second time + _, err = setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrCertificateAlreadyExists) +} + +func TestHandler_AddX509Cert_ForExistingNocCertificate(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // Store the NOC certificate + nocCertificate := intermediateCertificate(vendorAccAddress) + nocCertificate.SerialNumber = testconstants.TestSerialNumber + nocCertificate.IsNoc = true + + setup.Keeper.AddApprovedCertificate(setup.Ctx, nocCertificate) + setup.Keeper.AddNocCertificate(setup.Ctx, nocCertificate) + uniqueCertificate := types.UniqueCertificate{ + Issuer: nocCertificate.Issuer, + SerialNumber: nocCertificate.SerialNumber, + Present: true, + } + setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate) + + // store intermediate certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInappropriateCertificateType) +} + +func TestHandler_AddX509Cert_NoRootCert(t *testing.T) { + setup := Setup(t) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add intermediate certificate + intermediateCertificate := intermediateCertificate(vendorAccAddress) + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + + // add leaf x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInvalidCertificate) +} + +func TestHandler_AddX509Cert_RootIsNoc(t *testing.T) { + setup := Setup(t) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.IntermediateCertWithVid1Vid) + + // Add NOC root certificate + addNocX509RootCert := types.NewMsgAddNocX509RootCert(accAddress.String(), testconstants.RootCertPem) + _, err := setup.Handler(setup.Ctx, addNocX509RootCert) + require.NoError(t, err) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertPem) + _, err = setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInappropriateCertificateType) +} + +func TestHandler_AddX509Cert_ForDifferentSerialNumber(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // store intermediate certificate with different serial number + intermediateCertificate := intermediateCertificate(vendorAccAddress) + intermediateCertificate.SerialNumber = SerialNumber + setup.Keeper.SetUniqueCertificate( + setup.Ctx, + uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), + ) + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + + // store intermediate certificate second time + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certificates, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + + // check + require.Equal(t, 2, len(certificates.Certs)) + require.NotEqual(t, certificates.Certs[0].SerialNumber, certificates.Certs[1].SerialNumber) + + for _, certificate := range certificates.Certs { + require.Equal(t, addX509Cert.Cert, certificate.PemCert) + require.Equal(t, addX509Cert.Signer, certificate.Owner) + require.Equal(t, testconstants.IntermediateSubject, certificate.Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, certificate.SubjectKeyId) + require.False(t, certificate.IsRoot) + require.Equal(t, testconstants.RootSubject, certificate.RootSubject) + require.Equal(t, testconstants.RootSubjectKeyID, certificate.RootSubjectKeyId) + require.Equal(t, testconstants.IntermediateIssuer, certificate.Issuer) + require.Equal(t, testconstants.IntermediateAuthorityKeyID, certificate.AuthorityKeyId) + } +} + +func TestHandler_AddX509Cert_ForAbsentDirectParentCert(t *testing.T) { + setup := Setup(t) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add intermediate x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInvalidCertificate) +} + +func TestHandler_AddX509Cert_ForFailedCertificateVerification(t *testing.T) { + setup := Setup(t) + + // add invalid root + invalidRootCertificate := types.NewRootCertificate(testconstants.StubCertPem, + testconstants.RootSubject, testconstants.RootSubjectAsText, testconstants.RootSubjectKeyID, + testconstants.RootSerialNumber, setup.Trustee1.String(), []*types.Grant{}, []*types.Grant{}, testconstants.Vid) + setup.Keeper.AddApprovedCertificate(setup.Ctx, invalidRootCertificate) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add intermediate x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, pkitypes.ErrInvalidCertificate) +} + +func TestHandler_AddX509Cert_ForTree(t *testing.T) { + setup := Setup(t) + + // add root x509 certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add intermediate x509 certificate + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // add leaf x509 certificate + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) + _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + require.NoError(t, err) + + // query root certificate + rootCertificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Equal(t, testconstants.RootCertPem, rootCertificate.PemCert) + + // check child certificate identifiers of root certificate + rootCertChildren, _ := queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + + require.Equal(t, 1, len(rootCertChildren.CertIds)) + require.Equal(t, + certificateIdentifier(testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID), + *rootCertChildren.CertIds[0]) + + // query intermediate certificate + intermediateCertificate, _ := querySingleApprovedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, testconstants.IntermediateCertPem, intermediateCertificate.PemCert) + + // check child certificate identifiers of intermediate certificate + intermediateCertChildren, _ := queryChildCertificates( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + + require.Equal(t, 1, len(intermediateCertChildren.CertIds)) + require.Equal(t, + certificateIdentifier(testconstants.LeafSubject, testconstants.LeafSubjectKeyID), + *intermediateCertChildren.CertIds[0]) + + // query leaf certificate + leafCertificate, _ := querySingleApprovedCertificate(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Equal(t, testconstants.LeafCertPem, leafCertificate.PemCert) + + // check child certificate identifiers of leaf certificate + leafCertChildren, err := queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, leafCertChildren) +} + +//nolint:funlen +func TestHandler_AddX509Cert_EachChildCertRefersToTwoParentCerts(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCert := rootCertificate(setup.Trustee1) + + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCert) + setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate(rootCert.Subject, rootCert.SerialNumber)) + + // store second root certificate + rootCert = rootCertificate(setup.Trustee1) + rootCert.SerialNumber = SerialNumber + + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCert) + setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate(rootCert.Subject, rootCert.SerialNumber)) + + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // store intermediate certificate (it refers to two parent certificates) + intermediateCertificate := intermediateCertificate(vendorAccAddress) + intermediateCertificate.SerialNumber = SerialNumber + + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + setup.Keeper.SetUniqueCertificate( + setup.Ctx, + uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), + ) + + childCertID := certificateIdentifier(intermediateCertificate.Subject, intermediateCertificate.SubjectKeyId) + rootChildCertificates := types.ChildCertificates{ + Issuer: intermediateCertificate.Issuer, + AuthorityKeyId: intermediateCertificate.AuthorityKeyId, + CertIds: []*types.CertificateIdentifier{&childCertID}, + } + setup.Keeper.SetChildCertificates(setup.Ctx, rootChildCertificates) + + // store second intermediate certificate (it refers to two parent certificates) + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // store leaf certificate (it refers to two parent certificates) + addX509Cert = types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) + _, err = setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query root certificate + rootCertificates, _ := queryApprovedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Equal(t, 2, len(rootCertificates.Certs)) + + // check child certificate identifiers of root certificate + rootCertChildren, _ := queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + + require.Equal(t, 1, len(rootCertChildren.CertIds)) + require.Equal(t, + certificateIdentifier(testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID), + *rootCertChildren.CertIds[0]) + + // query intermediate certificate + intermediateCertificates, _ := queryApprovedCertificates( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 2, len(intermediateCertificates.Certs)) + + // check child certificate identifiers of intermediate certificate + intermediateCertChildren, _ := queryChildCertificates( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + + require.Equal(t, 1, len(intermediateCertChildren.CertIds)) + require.Equal(t, + certificateIdentifier(testconstants.LeafSubject, testconstants.LeafSubjectKeyID), + *intermediateCertChildren.CertIds[0]) + + // query leaf certificate + leafCertificates, _ := queryApprovedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Equal(t, 1, len(leafCertificates.Certs)) + + // check child certificate identifiers of intermediate certificate + leafCertChildren, err := queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, leafCertChildren) +} + +func TestHandler_AddX509Cert_ByNotOwnerButSameVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add first vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // Store an intermediate certificate with the first vendor account as the owner + intermediateCertificate := intermediateCertificate(vendorAccAddress1) + intermediateCertificate.SerialNumber = SerialNumber + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + setup.Keeper.AddApprovedCertificateBySubjectKeyID(setup.Ctx, intermediateCertificate) + setup.Keeper.SetUniqueCertificate( + setup.Ctx, + uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), + ) + + // add second vendor account with VID = 1 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add an intermediate certificate with the same subject and SKID by second vendor account + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress2.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) +} + +func TestHandler_AddX509Cert_ByOtherVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add first vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // Store an intermediate certificate with the first vendor account as the owner + intermediateCertificate := intermediateCertificate(vendorAccAddress1) + intermediateCertificate.SerialNumber = SerialNumber + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + setup.Keeper.AddApprovedCertificateBySubjectKeyID(setup.Ctx, intermediateCertificate) + setup.Keeper.SetUniqueCertificate( + setup.Ctx, + uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), + ) + + // add seconf vendor account with VID = 1000 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1) + + // add an intermediate certificate with the same subject and SKID by second vendor account + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress2.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) +} + +func TestHandler_AddX509Cert_SenderNotVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := createRootWithVidOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertWithVid1) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) +} + +func TestHandler_AddX509Cert_VIDScopedRoot(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := createPAACertWithNumericVidOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.PAACertWithNumericVidVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericPidVid) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certs, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(certs)) + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.PAICertWithNumericPidVidSubject, testconstants.PAICertWithNumericPidVidSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.PAICertWithNumericPidVidSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.PAICertWithNumericPidVidSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) +} + +func TestHandler_AddX509Cert_NonVIDScopedRoot(t *testing.T) { + accAddress := GenerateAccAddress() + + cases := []struct { + name string + rootCertOptions *rootCertOptions + childCert string + childCertSubject string + childCertSubjectKeyID string + accountVid int32 + }{ + { + name: "VidScopedChild", + rootCertOptions: createPAACertNoVidOptions(testconstants.PAICertWithVidVid), + childCert: testconstants.PAICertWithNumericVid, + childCertSubject: testconstants.PAICertWithNumericVidSubject, + childCertSubjectKeyID: testconstants.PAICertWithNumericVidSubjectKeyID, + accountVid: testconstants.PAICertWithVidVid, + }, + { + name: "NonVidScopedChild", + rootCertOptions: createTestRootCertOptions(), + childCert: testconstants.IntermediateCertPem, + childCertSubject: testconstants.IntermediateSubject, + childCertSubjectKeyID: testconstants.IntermediateSubjectKeyID, + accountVid: testconstants.Vid, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + setup := Setup(t) + // store root certificate + proposeAndApproveRootCertificate(setup, setup.Trustee1, tc.rootCertOptions) + + // add vendor account + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, tc.accountVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), tc.childCert) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certs, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(certs)) + intermediateCerts, _ := queryApprovedCertificates(setup, tc.childCertSubject, tc.childCertSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, tc.childCertSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, tc.childCertSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) + }) + } +} + +func TestHandler_AddX509Cert_VIDScopedRoot_NegativeCases(t *testing.T) { + accAddress := GenerateAccAddress() + + cases := []struct { + name string + rootCertOptions *rootCertOptions + childCert string + accountVid int32 + err error + }{ + { + name: "IncorrectChildVid", + rootCertOptions: createRootWithVidOptions(), + childCert: testconstants.IntermediateCertWithVid2, + accountVid: testconstants.RootCertWithVidVid, + err: pkitypes.ErrCertVidNotEqualToRootVid, + }, + { + name: "IncorrectAccountVid", + rootCertOptions: createRootWithVidOptions(), + childCert: testconstants.IntermediateCertWithVid1, + accountVid: testconstants.Vid, + err: pkitypes.ErrCertVidNotEqualAccountVid, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + setup := Setup(t) + // store root certificate + proposeAndApproveRootCertificate(setup, setup.Trustee1, tc.rootCertOptions) + + // add vendor account + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, tc.accountVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), tc.childCert) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, tc.err) + }) + } +} + +func TestHandler_AddX509Cert_NonVIDScopedRoot_NegativeCases(t *testing.T) { + accAddress := GenerateAccAddress() + + cases := []struct { + name string + rootCertOptions *rootCertOptions + childCert string + accountVid int32 + err error + }{ + { + name: "IncorrectChildVid", + rootCertOptions: createPAACertNoVidOptions(testconstants.Vid), + childCert: testconstants.PAICertWithNumericVid, + accountVid: testconstants.Vid, + err: pkitypes.ErrCertVidNotEqualToRootVid, + }, + { + name: "IncorrectAccountVid", + rootCertOptions: createPAACertNoVidOptions(testconstants.PAICertWithVidVid), + childCert: testconstants.PAICertWithNumericVid, + accountVid: testconstants.Vid, + err: pkitypes.ErrCertVidNotEqualAccountVid, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + setup := Setup(t) + // store root certificate + proposeAndApproveRootCertificate(setup, setup.Trustee1, tc.rootCertOptions) + + // add vendor account + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, tc.accountVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), tc.childCert) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.ErrorIs(t, err, tc.err) + }) + } +} diff --git a/x/pki/handler_remove_non_root_cert_test.go b/x/pki/handler_remove_non_root_cert_test.go new file mode 100644 index 000000000..445c20bc0 --- /dev/null +++ b/x/pki/handler_remove_non_root_cert_test.go @@ -0,0 +1,482 @@ +package pki + +import ( + "testing" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/require" + testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" + pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestHandler_RemoveX509Cert_BySerialNumber(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertWithSameSubjectAndSKID1, + subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, + subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, + info: testconstants.Info, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // Add intermediate certificates + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID1) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // Add intermediate certificates with sam subject and SKID but different serial number + addIntermediateX509Cert = types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID2) + _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // Add a leaf certificate + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertWithSameSubjectAndSKID) + _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + require.NoError(t, err) + + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 2, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) + + // remove intermediate certificate by serial number + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + // check that only root, intermediate(with serial number 3) and leaf certificates exists + allCerts, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 3, len(allCerts)) + require.Equal(t, 3, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) + leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 1, len(leafCerts.Certs)) + + intermediateCerts, _ = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, intermediateCerts.Certs[0].SerialNumber) + + // remove intermediate certificate by serial number and check that leaf cert is not removed + removeX509Cert = types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + allCerts, _ = queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(allCerts)) + require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) + + _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that unique certificates does not exists + found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) + require.Equal(t, false, found) + found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) + require.Equal(t, false, found) + + leafCerts, _ = queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 1, len(leafCerts.Certs)) +} + +func TestHandler_RemoveX509Cert_RevokedAndApprovedCertificate(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertWithSameSubjectAndSKID1, + subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, + subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, + info: testconstants.Info, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // Add an intermediate certificate + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID1) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // get certificates for further comparison + allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.NotNil(t, allCerts) + require.Equal(t, 2, len(allCerts)) + require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) + + // revoke an intermediate certificate + revokeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + // Add an intermediate certificate with new serial number + addIntermediateX509Cert = types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID2) + _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) + require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, intermediateCerts.Certs[0].SerialNumber) + + // remove an intermediate certificate + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + // check that only root and leaf certificates exists + allCerts, _ = queryAllApprovedCertificates(setup) + require.Equal(t, 1, len(allCerts)) + require.Equal(t, true, allCerts[0].Certs[0].IsRoot) + _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + _, err = queryRevokedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that unique certificates does not exists + found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) + require.Equal(t, false, found) + found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) + require.Equal(t, false, found) +} + +func TestHandler_RemoveX509Cert_RevokedCertificate(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertPem, + subject: testconstants.RootSubject, + subjectKeyID: testconstants.RootSubjectKeyID, + info: testconstants.Info, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // Add two intermediate certificates again + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.IntermediateSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) + + // revoke intermediate certificate by serial number + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + false, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + + revokedCerts, _ := queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(revokedCerts.Certs)) + require.Equal(t, testconstants.IntermediateSubject, revokedCerts.Certs[0].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCerts.Certs[0].SubjectKeyId) + + // remove intermediate certificate by serial number + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + allCerts, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 1, len(allCerts)) + require.Equal(t, true, allCerts[0].Certs[0].IsRoot) + + _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + _, err = queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that unique certificate does not exists + found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber) + require.Equal(t, false, found) +} + +func TestHandler_RemoveX509Cert_CertificateDoesNotExist(t *testing.T) { + setup := Setup(t) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber) + _, err := setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) +} + +func TestHandler_RemoveX509Cert_EmptyCertificatesList(t *testing.T) { + setup := Setup(t) + + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + setup.Keeper.SetApprovedCertificates( + setup.Ctx, + types.ApprovedCertificates{ + Subject: testconstants.IntermediateSubject, + SubjectKeyId: testconstants.IntermediateSubjectKeyID, + }, + ) + + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "") + _, err := setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) +} + +func TestHandler_RemoveX509Cert_ByNotOwnerButSameVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add first vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add x509 certificate by fist vendor account + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress1.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // add second vendor account with VID = 1 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // remove x509 certificate by second vendor account + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress2.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + // check that certificate removed from 'approved certificates' list + _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that certificate removed from 'approved certificates by subject' list + _, err = queryApprovedCertificatesBySubject(setup, testconstants.IntermediateSubject) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that certificate removed from 'approved certificates by SKID' list + approvedCerts, err := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.NoError(t, err) + require.Equal(t, 0, len(approvedCerts)) + + // check that unique certificate key is not registered + require.False(t, setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, + testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) +} + +func TestHandler_RemoveX509Cert_ByOtherVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add fist vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add x509 certificate by `setup.Trustee` + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress1.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // add scond vendor account with VID = 1000 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1) + + // revoke x509 certificate by second vendor account + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress2.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) +} + +func TestHandler_RemoveX509Cert_SenderNotVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := createRootWithVidOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertWithVid1) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + removeX509Cert := types.NewMsgRemoveX509Cert( + setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "invalid") + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) +} + +func TestHandler_RemoveX509Cert_ForRootCertificate(t *testing.T) { + setup := Setup(t) + + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber) + _, err := setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) +} + +func TestHandler_RemoveX509Cert_InvalidSerialNumber(t *testing.T) { + setup := Setup(t) + + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "invalid") + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) +} + +func TestHandler_RemoveX509Cert_BySubjectAndSKID(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertWithSameSubjectAndSKID1, + subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, + subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, + info: testconstants.Info, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // Add two intermediate certificates + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID1) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + addIntermediateX509Cert = types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID2) + _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // Add a leaf certificate + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertWithSameSubjectAndSKID) + _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + require.NoError(t, err) + + // get certificates for further comparison + allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.NotNil(t, allCerts) + require.Equal(t, 3, len(allCerts)) + require.Equal(t, 4, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) + + // remove all intermediate certificates but leave leaf certificate + removeX509Cert := types.NewMsgRemoveX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, + testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, + "", + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.NoError(t, err) + + // check that only root and leaf certificates exists + allCerts, _ = queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(allCerts)) + require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) + _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, codes.NotFound, status.Code(err)) + // check that unique certificates does not exists + found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) + require.Equal(t, false, found) + found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) + require.Equal(t, false, found) + + leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) + require.Equal(t, 1, len(leafCerts.Certs)) + require.Equal(t, testconstants.LeafCertWithSameSubjectAndSKIDSerialNumber, leafCerts.Certs[0].SerialNumber) +} diff --git a/x/pki/handler_revoke_non_root_cert_test.go b/x/pki/handler_revoke_non_root_cert_test.go new file mode 100644 index 000000000..9395210d4 --- /dev/null +++ b/x/pki/handler_revoke_non_root_cert_test.go @@ -0,0 +1,458 @@ +package pki + +import ( + "testing" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/require" + testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" + pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestHandler_RevokeX509Cert_CertificateDoesNotExist(t *testing.T) { + setup := Setup(t) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // revoke x509 certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + false, + testconstants.Info, + ) + _, err := setup.Handler(setup.Ctx, revokeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) +} + +func TestHandler_RevokeX509Cert_CertificateDoesNotExistBySerialNumber(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // Add intermediate certificate + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // revoke x509 certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + "invalid", + false, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) +} + +func TestHandler_RevokeX509Cert_ForRootCertificate(t *testing.T) { + setup := Setup(t) + + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // revoke x509 root certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.RootSubject, + testconstants.RootSubjectKeyID, + testconstants.RootSerialNumber, + false, + testconstants.Info, + ) + _, err := setup.Handler(setup.Ctx, revokeX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) +} + +func TestHandler_RevokeX509Cert_ForTree(t *testing.T) { + setup := Setup(t) + + // add root x509 certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add intermediate x509 certificate + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + + // add leaf x509 certificate + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) + _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + require.NoError(t, err) + + // check that intermediate nd leaf certificates removed from subject-key-id -> certs map + certs, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(certs)) + certs, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.LeafSubjectKeyID) + require.Equal(t, 1, len(certs)) + + // revoke x509 certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + "", + true, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + // check that intermediate certificate has been revoked + allRevokedCertificates, _ := queryAllRevokedCertificates(setup) + require.Equal(t, 2, len(allRevokedCertificates)) + require.Equal(t, testconstants.LeafSubject, allRevokedCertificates[0].Subject) + require.Equal(t, testconstants.LeafSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) + require.Equal(t, 1, len(allRevokedCertificates[0].Certs)) + require.Equal(t, testconstants.LeafCertPem, allRevokedCertificates[0].Certs[0].PemCert) + require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[1].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[1].SubjectKeyId) + require.Equal(t, 1, len(allRevokedCertificates[1].Certs)) + require.Equal(t, testconstants.IntermediateCertPem, allRevokedCertificates[1].Certs[0].PemCert) + + // check that root certificate stays approved + allApprovedCertificates, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 1, len(allApprovedCertificates)) + require.Equal(t, testconstants.RootSubject, allApprovedCertificates[0].Subject) + require.Equal(t, testconstants.RootSubjectKeyID, allApprovedCertificates[0].SubjectKeyId) + // check that root certificate(by subject key id) stays approved + allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.RootSubjectKeyID) + require.Equal(t, 1, len(allApprovedCertificates)) + require.Equal(t, testconstants.RootSubjectKeyID, allApprovedCertificates[0].SubjectKeyId) + // check that intermediate and leaf certificates removed from subject-key-id -> certs map + allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 0, len(allApprovedCertificates)) + allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.LeafSubjectKeyID) + require.Equal(t, 0, len(allApprovedCertificates)) + + // check that no proposed certificate revocations have been created + allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) + require.NoError(t, err) + require.Equal(t, 0, len(allProposedCertificateRevocations)) + + // check that no child certificate identifiers are now registered for root certificate + _, err = queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that no child certificate identifiers are registered for revoked intermediate certificate + _, err = queryChildCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that no child certificate identifiers are registered for revoked leaf certificate + _, err = queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) +} + +func TestHandler_RevokeX509Cert_ByNotOwnerButSameVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add first vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add x509 certificate by first vendor account + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress1.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // add second vendor account with VID = 1 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // revoke x509 certificate by second vendor account + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress2.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + false, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + // check that intermediate certificate has been added to revoked list + revokedCertificates, _ := queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, testconstants.IntermediateSubject, revokedCertificates.Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCertificates.SubjectKeyId) + require.Equal(t, 1, len(revokedCertificates.Certs)) + require.Equal(t, intermediateCertificate(vendorAccAddress1), *revokedCertificates.Certs[0]) + + // check that revoked certificate removed from approved certificates list + _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that revoked certificate removed from 'approved certificates' by subject list + _, err = queryApprovedCertificatesBySubject(setup, testconstants.IntermediateSubject) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that revoked certificate removed from 'approved certificates' by SKID list + approvedCerts, err := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.NoError(t, err) + require.Equal(t, 0, len(approvedCerts)) + + // check that unique certificate key stays registered + require.True(t, setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, + testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) +} + +func TestHandler_RevokeX509Cert_ByOtherVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // add first vendor account with VID = 1 + vendorAccAddress1 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add x509 certificate by first vendor account + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress1.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // add second vendor account with VID = 1000 + vendorAccAddress2 := GenerateAccAddress() + setup.AddAccount(vendorAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1) + + // revoke x509 certificate by second vendor account + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress2.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + false, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) +} + +func TestHandler_RevokeX509Cert_SenderNotVendor(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := createRootWithVidOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertWithVid1) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + removeX509Cert := types.NewMsgRevokeX509Cert( + setup.Trustee1.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + testconstants.IntermediateSerialNumber, + false, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, removeX509Cert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) +} + +func TestHandler_RevokeX509Cert(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertificate := rootCertificate(setup.Trustee1) + setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // get intermediate certificate by subject-key-id + certsBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(certsBySubjectKeyID)) + // get certificate for further comparison + certificateBeforeRevocation, _ := querySingleApprovedCertificate( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.NotNil(t, certificateBeforeRevocation) + + // revoke x509 certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "", false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + // check that intermediate certificate has been revoked + allRevokedCertificates, _ := queryAllRevokedCertificates(setup) + require.Equal(t, 1, len(allRevokedCertificates)) + require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[0].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) + require.Equal(t, 1, len(allRevokedCertificates[0].Certs)) + require.Equal(t, *certificateBeforeRevocation, *allRevokedCertificates[0].Certs[0]) + + // check that root certificate stays approved + allApprovedCertificates, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 1, len(allApprovedCertificates)) + require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[0].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) + + // check that intermediate certificate removed from subject-key-id -> certs map + certsBySubjectKeyID, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 0, len(certsBySubjectKeyID)) + + // check that no proposed certificate revocations have been created + allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) + require.NoError(t, err) + require.Equal(t, 0, len(allProposedCertificateRevocations)) + + // check that child certificate identifiers list of issuer do not exist anymore + _, err = queryChildCertificates(setup, testconstants.IntermediateIssuer, testconstants.IntermediateAuthorityKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that unique certificate key stays registered + require.True(t, setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, + testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) +} + +func TestHandler_RevokeX509Cert_BySerialNumber(t *testing.T) { + setup := Setup(t) + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + + // Add two intermediate certificates + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) + _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) + require.NoError(t, err) + intermediateCertificate := intermediateCertificate(vendorAccAddress) + intermediateCertificate.SerialNumber = SerialNumber + setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + setup.Keeper.AddApprovedCertificateBySubjectKeyID(setup.Ctx, intermediateCertificate) + setup.Keeper.SetUniqueCertificate( + setup.Ctx, + uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), + ) + // Add a leaf certificate + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) + _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + require.NoError(t, err) + + // get certificates for further comparison + allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.NotNil(t, allCerts) + require.Equal(t, 3, len(allCerts)) + require.Equal(t, 4, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) + + // revoke only an intermediate certificate + revokeX509Cert := types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber, false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + // check that proposed certificate revocation does not exist anymore + _, err = queryProposedCertificateRevocation(setup, testconstants.IntermediateSerialNumber) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that only root, intermediate and leaf certificates exists + allCerts, _ = queryAllApprovedCertificates(setup) + require.Equal(t, 3, len(allCerts)) + require.Equal(t, 3, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, SerialNumber, intermediateCerts.Certs[0].SerialNumber) + leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Equal(t, 1, len(leafCerts.Certs)) + require.Equal(t, testconstants.LeafSerialNumber, leafCerts.Certs[0].SerialNumber) + + // query and check revoked certificate + revokedCertificate, _ := querySingleRevokedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.NotNil(t, revokedCertificate) + require.Equal(t, testconstants.IntermediateSubject, revokedCertificate.Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCertificate.SubjectKeyId) + require.Equal(t, testconstants.IntermediateSerialNumber, revokedCertificate.SerialNumber) + + // revoke intermediate and leaf certificates + revokeX509Cert = types.NewMsgRevokeX509Cert( + vendorAccAddress.String(), + testconstants.IntermediateSubject, + testconstants.IntermediateSubjectKeyID, + SerialNumber, + true, + testconstants.Info, + ) + _, err = setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + _, err = queryProposedCertificateRevocation(setup, testconstants.IntermediateSerialNumber) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that only root certificate exists + certsAfterRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.Equal(t, 1, len(certsAfterRevocation)) + require.Equal(t, 1, len(certsAfterRevocation[0].Certs)) + require.Equal(t, testconstants.RootSerialNumber, certsAfterRevocation[0].Certs[0].SerialNumber) + + // query and check revoked certificate + revokedCerts, _ := queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + require.Equal(t, 2, len(revokedCerts.Certs)) + require.Equal(t, testconstants.IntermediateSubject, revokedCerts.Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCerts.SubjectKeyId) + + // query and check revoked certificate + revokedCerts, _ = queryRevokedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + require.Equal(t, 1, len(revokedCerts.Certs)) + require.Equal(t, testconstants.LeafSubject, revokedCerts.Subject) + require.Equal(t, testconstants.LeafSubjectKeyID, revokedCerts.SubjectKeyId) +} diff --git a/x/pki/handler_test.go b/x/pki/handler_test.go index e091030a3..7faeb0606 100644 --- a/x/pki/handler_test.go +++ b/x/pki/handler_test.go @@ -712,1720 +712,580 @@ func TestHandler_AddX509RootCertsBySubjectKeyId(t *testing.T) { require.Equal(t, testconstants.PAACertWithSameSubjectID2Subject, approvedCertificates[0].Certs[1].Subject) } -func TestHandler_AddX509Cert(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ByTrusteeOwner(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + // propose x509 root certificate by `setup.Trustee` and approve by another trustee + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - for i, role := range []dclauthtypes.AccountRole{ - dclauthtypes.Vendor, - dclauthtypes.CertificationCenter, - dclauthtypes.Trustee, - dclauthtypes.NodeAdmin, - } { - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) + // propose revocation of x509 root certificate by `setup.Trustee` + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.NoError(t, err) - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) + // query and check proposed certificate revocation + proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) + require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) + require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) + require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee1.String())) - // query certificate - certificate, _ := querySingleApprovedCertificate( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - - certificateBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(certificateBySubjectKeyID)) - require.Equal(t, i+1, len(certificateBySubjectKeyID[0].Certs)) - - certs := make([]*types.Certificate, 0) - certs = append(certs, certificate, certificateBySubjectKeyID[0].Certs[i]) - for _, cert := range certs { - // check - require.Equal(t, addX509Cert.Cert, cert.PemCert) - require.Equal(t, addX509Cert.Signer, cert.Owner) - require.Equal(t, testconstants.IntermediateSubject, cert.Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, cert.SubjectKeyId) - require.Equal(t, testconstants.IntermediateSerialNumber, cert.SerialNumber) - require.False(t, cert.IsRoot) - require.Equal(t, testconstants.IntermediateIssuer, cert.Issuer) - require.Equal(t, testconstants.IntermediateAuthorityKeyID, cert.AuthorityKeyId) - require.Equal(t, testconstants.RootSubject, cert.RootSubject) - require.Equal(t, testconstants.RootSubjectKeyID, cert.RootSubjectKeyId) - } + // check that approved certificate still exists + certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.NotNil(t, certificate) - // check that unique certificate key is registered - require.True(t, setup.Keeper.IsUniqueCertificatePresent( - setup.Ctx, testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) - - // check that child certificates of issuer contains certificate identifier - issuerChildren, _ := queryChildCertificates( - setup, testconstants.IntermediateIssuer, testconstants.IntermediateAuthorityKeyID) - require.Equal(t, 1, len(issuerChildren.CertIds)) - require.Equal(t, - &types.CertificateIdentifier{ - Subject: testconstants.IntermediateSubject, - SubjectKeyId: testconstants.IntermediateSubjectKeyID, - }, - issuerChildren.CertIds[0]) - - // check that no proposed certificate has been created - _, err = queryProposedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) + // check that revoked certificate does not exist + _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) - // cleanup for next iteration - setup.Keeper.RemoveApprovedCertificates(setup.Ctx, - testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - setup.Keeper.RemoveUniqueCertificate(setup.Ctx, - testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber) - setup.Keeper.RemoveChildCertificates(setup.Ctx, - testconstants.IntermediateIssuer, testconstants.IntermediateAuthorityKeyID) - } + // check that unique certificate key stays registered + require.True(t, + setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) } -func TestHandler_AddX509Cert_RootVID_Equal_To_CertVID_And_AccountVID(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ByTrusteeNotOwner(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertOptions := createPAACertWithNumericVidOptions() + // propose x509 root certificate by `setup.Trustee` and approve by another trustee + rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.PAACertWithNumericVidVid) + // add another trustee + anotherTrustee := GenerateAccAddress() + setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericPidVid) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // propose revocation of x509 root certificate by new trustee + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + anotherTrustee.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - // query certificate - certs, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 2, len(certs)) - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.PAICertWithNumericPidVidSubject, testconstants.PAICertWithNumericPidVidSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.PAICertWithNumericPidVidSubject, intermediateCerts.Certs[0].Subject) - require.Equal(t, testconstants.PAICertWithNumericPidVidSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) -} - -func TestHandler_AddX509Cert_Non_VID_Scoped_Root__ChildVID_Equal_To_AccountVID(t *testing.T) { - setup := Setup(t) - // store root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.PAACertNoVid, - info: testconstants.Info, - subject: testconstants.PAACertNoVidSubject, - subjectKeyID: testconstants.PAACertNoVidSubjectKeyID, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // query and check proposed certificate revocation + proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) + require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) + require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) + require.True(t, proposedRevocation.HasRevocationFrom(anotherTrustee.String())) - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 65522) + // check that approved certificate still exists + certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.NotNil(t, certificate) - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericVid) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) + // check that revoked certificate does not exist + _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) - // query certificate - certs, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 2, len(certs)) - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.PAICertWithNumericVidSubject, testconstants.PAICertWithNumericVidSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.PAICertWithNumericVidSubject, intermediateCerts.Certs[0].Subject) - require.Equal(t, testconstants.PAICertWithNumericVidSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) + // check that unique certificate key stays registered + require.True(t, + setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) } -func TestHandler_AddX509Cert_Root_VID_Does_Not_Equal_To_ChildVID(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ByNotTrustee(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.RootCertWithVid, - info: testconstants.Info, - subject: testconstants.RootCertWithVidSubject, - subjectKeyID: testconstants.RootCertWithVidSubjectKeyID, - vid: testconstants.RootCertWithVidVid, - } + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + for _, role := range []dclauthtypes.AccountRole{ + dclauthtypes.Vendor, + dclauthtypes.CertificationCenter, + dclauthtypes.NodeAdmin, + } { + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertWithVid2) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertVidNotEqualToRootVid.Is(err)) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + accAddress.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + } } -func TestHandler_AddX509Cert_Root_VID_Does_Not_Equal_To_AccountVID(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_CertificateDoesNotExist(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.RootCertWithVid, - info: testconstants.Info, - subject: testconstants.RootCertWithVidSubject, - subjectKeyID: testconstants.RootCertWithVidSubjectKeyID, - vid: testconstants.RootCertWithVidVid, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1111) - - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertWithVid1) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // propose revocation of not existing certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.Error(t, err) - require.True(t, pkitypes.ErrCertVidNotEqualAccountVid.Is(err)) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) } -func TestHandler_AddX509Cert_Non_Root_VID__Child_VID_Does_Not_Equal_To_AccountVID(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_CertificateDoesNotExistBySerialNumber(t *testing.T) { setup := Setup(t) - - // store root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.PAACertNoVid, - info: testconstants.Info, - subject: testconstants.PAACertNoVidSubject, - subjectKeyID: testconstants.PAACertNoVidSubjectKeyID, - } + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1111) - - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericVid) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // revoke x509 certificate + revokeX509Cert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), + testconstants.RootSubject, + testconstants.RootSubjectKeyID, + "invalid", + false, + testconstants.Info, + ) + _, err := setup.Handler(setup.Ctx, revokeX509Cert) require.Error(t, err) - require.True(t, pkitypes.ErrCertVidNotEqualAccountVid.Is(err)) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) } -func TestHandler_AddX509Cert_ForInvalidCertificate(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ForProposedCertificate(t *testing.T) { setup := Setup(t) - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.StubCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInvalidCertificate.Is(err)) -} + // propose x509 root certificate + proposeAddX509RootCert := types.NewMsgProposeAddX509RootCert(setup.Trustee1.String(), testconstants.RootCertPem, testconstants.Info, testconstants.Vid) + _, err := setup.Handler(setup.Ctx, proposeAddX509RootCert) + require.NoError(t, err) -func TestHandler_AddX509Cert_ForRootCertificate(t *testing.T) { - setup := Setup(t) + // check that proposed certificate is present + proposedCertificate, _ := queryProposedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.NotNil(t, proposedCertificate) - // add root certificate as leaf x509 certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.RootCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // propose revocation of proposed root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.Error(t, err) - require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) + require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) } -func TestHandler_AddX509Cert_ForDuplicate(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ProposedRevocationAlreadyExists(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // store intermediate certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - // store intermediate certificate second time - _, err = setup.Handler(setup.Ctx, addX509Cert) + // store another trustee + anotherTrustee := GenerateAccAddress() + setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) + + // propose revocation of the same x509 root certificate again + proposeRevokeX509RootCert = types.NewMsgProposeRevokeX509RootCert( + anotherTrustee.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.Error(t, err) - require.True(t, pkitypes.ErrCertificateAlreadyExists.Is(err)) + require.True(t, pkitypes.ErrProposedCertificateRevocationAlreadyExists.Is(err)) } -func TestHandler_AddX509Cert_ForNocCertificate(t *testing.T) { +func TestHandler_ProposeRevokeX509RootCert_ForNonRootCertificate(t *testing.T) { setup := Setup(t) - // store root certificate + // store x509 root certificate rootCertificate := rootCertificate(setup.Trustee1) setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - // Store the NOC certificate + // Add vendor account vendorAccAddress := GenerateAccAddress() setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) - nocCertificate := intermediateCertificate(vendorAccAddress) - nocCertificate.SerialNumber = testconstants.TestSerialNumber - nocCertificate.IsNoc = true - - setup.Keeper.AddApprovedCertificate(setup.Ctx, nocCertificate) - // TODO: add the certificate to the ICA store after the store is implemented - uniqueCertificate := types.UniqueCertificate{ - Issuer: nocCertificate.Issuer, - SerialNumber: nocCertificate.SerialNumber, - Present: true, - } - setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate) - - // store intermediate certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) + // store x509 intermediate certificate + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // propose revocation of x509 intermediate certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.Error(t, err) require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) } -func TestHandler_AddX509Cert_ForDifferentSerialNumber(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_ForNotEnoughApprovals(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // store intermediate certificate with different serial number - intermediateCertificate := intermediateCertificate(setup.Trustee1) - intermediateCertificate.SerialNumber = SerialNumber - setup.Keeper.SetUniqueCertificate( - setup.Ctx, - uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), - ) - setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) + // Add 1 more trustee (this will bring the total trustee's to 4) + anotherTrustee := GenerateAccAddress() + setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - // store intermediate certificate second time - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - // query certificate - certificates, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + // approve + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) + require.NoError(t, err) - // check - require.Equal(t, 2, len(certificates.Certs)) - require.NotEqual(t, certificates.Certs[0].SerialNumber, certificates.Certs[1].SerialNumber) + // query and check proposed certificate revocation + proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) + require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) + require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) + require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee1.String())) + require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee2.String())) - for _, certificate := range certificates.Certs { - require.Equal(t, addX509Cert.Cert, certificate.PemCert) - require.Equal(t, addX509Cert.Signer, certificate.Owner) - require.Equal(t, testconstants.IntermediateSubject, certificate.Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, certificate.SubjectKeyId) - require.False(t, certificate.IsRoot) - require.Equal(t, testconstants.RootSubject, certificate.RootSubject) - require.Equal(t, testconstants.RootSubjectKeyID, certificate.RootSubjectKeyId) - require.Equal(t, testconstants.IntermediateIssuer, certificate.Issuer) - require.Equal(t, testconstants.IntermediateAuthorityKeyID, certificate.AuthorityKeyId) - } + // check that approved certificate still exists + certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.NotNil(t, certificate) + + // check that revoked certificate does not exist + _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + + // check that unique certificate key stays registered + require.True(t, + setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) } -func TestHandler_AddX509Cert_ForDifferentSerialNumberDifferentSigner(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_ForEnoughApprovals(t *testing.T) { setup := Setup(t) - // store root certificate - rootCertificate := rootCertificate(testconstants.Address1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) + // propose and approve x509 root certificate + rootCertOptions := createTestRootCertOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // store intermediate certificate with different serial number - intermediateCertificate := intermediateCertificate(testconstants.Address1) - intermediateCertificate.SerialNumber = SerialNumber - setup.Keeper.SetUniqueCertificate( - setup.Ctx, - uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), - ) - setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) - - // store intermediate certificate second time - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) -} - -func TestHandler_AddX509Cert_ForAbsentDirectParentCert(t *testing.T) { - setup := Setup(t) - - // add intermediate x509 certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInvalidCertificate.Is(err)) -} - -func TestHandler_AddX509Cert_ForNoRootCert(t *testing.T) { - setup := Setup(t) - - // add intermediate certificate - intermediateCertificate := intermediateCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) - - // add leaf x509 certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInvalidCertificate.Is(err)) -} - -func TestHandler_AddX509Cert_ForFailedCertificateVerification(t *testing.T) { - setup := Setup(t) - - // add invalid root - invalidRootCertificate := types.NewRootCertificate(testconstants.StubCertPem, - testconstants.RootSubject, testconstants.RootSubjectAsText, testconstants.RootSubjectKeyID, - testconstants.RootSerialNumber, setup.Trustee1.String(), []*types.Grant{}, []*types.Grant{}, testconstants.Vid) - setup.Keeper.AddApprovedCertificate(setup.Ctx, invalidRootCertificate) - - // add intermediate x509 certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInvalidCertificate.Is(err)) -} - -func TestHandler_AddX509Cert_ForTree(t *testing.T) { - setup := Setup(t) - - // add root x509 certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // add intermediate x509 certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // add leaf x509 certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) - _, err = setup.Handler(setup.Ctx, addLeafX509Cert) - require.NoError(t, err) - - // query root certificate - rootCertificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Equal(t, testconstants.RootCertPem, rootCertificate.PemCert) - - // check child certificate identifiers of root certificate - rootCertChildren, _ := queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - - require.Equal(t, 1, len(rootCertChildren.CertIds)) - require.Equal(t, - certificateIdentifier(testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID), - *rootCertChildren.CertIds[0]) - - // query intermediate certificate - intermediateCertificate, _ := querySingleApprovedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, testconstants.IntermediateCertPem, intermediateCertificate.PemCert) - - // check child certificate identifiers of intermediate certificate - intermediateCertChildren, _ := queryChildCertificates( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - - require.Equal(t, 1, len(intermediateCertChildren.CertIds)) - require.Equal(t, - certificateIdentifier(testconstants.LeafSubject, testconstants.LeafSubjectKeyID), - *intermediateCertChildren.CertIds[0]) - - // query leaf certificate - leafCertificate, _ := querySingleApprovedCertificate(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Equal(t, testconstants.LeafCertPem, leafCertificate.PemCert) - - // check child certificate identifiers of leaf certificate - leafCertChildren, err := queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, leafCertChildren) -} - -//nolint:funlen -func TestHandler_AddX509Cert_EachChildCertRefersToTwoParentCerts(t *testing.T) { - setup := Setup(t) - - // store root certificate - rootCert := rootCertificate(setup.Trustee1) - - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCert) - setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate(rootCert.Subject, rootCert.SerialNumber)) - - // store second root certificate - rootCert = rootCertificate(setup.Trustee1) - rootCert.SerialNumber = SerialNumber - - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCert) - setup.Keeper.SetUniqueCertificate(setup.Ctx, uniqueCertificate(rootCert.Subject, rootCert.SerialNumber)) - - // store intermediate certificate (it refers to two parent certificates) - intermediateCertificate := intermediateCertificate(setup.Trustee1) - intermediateCertificate.SerialNumber = SerialNumber - - setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) - setup.Keeper.SetUniqueCertificate( - setup.Ctx, - uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), - ) - - childCertID := certificateIdentifier(intermediateCertificate.Subject, intermediateCertificate.SubjectKeyId) - rootChildCertificates := types.ChildCertificates{ - Issuer: intermediateCertificate.Issuer, - AuthorityKeyId: intermediateCertificate.AuthorityKeyId, - CertIds: []*types.CertificateIdentifier{&childCertID}, - } - setup.Keeper.SetChildCertificates(setup.Ctx, rootChildCertificates) - - // store second intermediate certificate (it refers to two parent certificates) - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) - - // store leaf certificate (it refers to two parent certificates) - addX509Cert = types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) - _, err = setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) - - // query root certificate - rootCertificates, _ := queryApprovedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Equal(t, 2, len(rootCertificates.Certs)) - - // check child certificate identifiers of root certificate - rootCertChildren, _ := queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - - require.Equal(t, 1, len(rootCertChildren.CertIds)) - require.Equal(t, - certificateIdentifier(testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID), - *rootCertChildren.CertIds[0]) - - // query intermediate certificate - intermediateCertificates, _ := queryApprovedCertificates( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 2, len(intermediateCertificates.Certs)) - - // check child certificate identifiers of intermediate certificate - intermediateCertChildren, _ := queryChildCertificates( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - - require.Equal(t, 1, len(intermediateCertChildren.CertIds)) - require.Equal(t, - certificateIdentifier(testconstants.LeafSubject, testconstants.LeafSubjectKeyID), - *intermediateCertChildren.CertIds[0]) - - // query leaf certificate - leafCertificates, _ := queryApprovedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Equal(t, 1, len(leafCertificates.Certs)) - - // check child certificate identifiers of intermediate certificate - leafCertChildren, err := queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, leafCertChildren) -} - -func TestHandler_ProposeRevokeX509RootCert_ByTrusteeOwner(t *testing.T) { - setup := Setup(t) - - // propose x509 root certificate by `setup.Trustee` and approve by another trustee - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // propose revocation of x509 root certificate by `setup.Trustee` - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // query and check proposed certificate revocation - proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) - require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) - require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) - require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee1.String())) - - // check that approved certificate still exists - certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.NotNil(t, certificate) - - // check that revoked certificate does not exist - _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificate key stays registered - require.True(t, - setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) -} - -func TestHandler_ProposeRevokeX509RootCert_ByTrusteeNotOwner(t *testing.T) { - setup := Setup(t) - - // propose x509 root certificate by `setup.Trustee` and approve by another trustee - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // store another trustee - anotherTrustee := GenerateAccAddress() - setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - - // propose revocation of x509 root certificate by new trustee - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - anotherTrustee.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // query and check proposed certificate revocation - proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) - require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) - require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) - require.True(t, proposedRevocation.HasRevocationFrom(anotherTrustee.String())) - - // check that approved certificate still exists - certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.NotNil(t, certificate) - - // check that revoked certificate does not exist - _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificate key stays registered - require.True(t, - setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) -} - -func TestHandler_ProposeRevokeX509RootCert_ByNotTrustee(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - for _, role := range []dclauthtypes.AccountRole{ - dclauthtypes.Vendor, - dclauthtypes.CertificationCenter, - dclauthtypes.NodeAdmin, - } { - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - accAddress.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) - } -} - -func TestHandler_ProposeRevokeX509RootCert_CertificateDoesNotExist(t *testing.T) { - setup := Setup(t) - - // propose revocation of not existing certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} - -func TestHandler_ProposeRevokeX509RootCert_ForProposedCertificate(t *testing.T) { - setup := Setup(t) - - // propose x509 root certificate - proposeAddX509RootCert := types.NewMsgProposeAddX509RootCert(setup.Trustee1.String(), testconstants.RootCertPem, testconstants.Info, testconstants.Vid) - _, err := setup.Handler(setup.Ctx, proposeAddX509RootCert) - require.NoError(t, err) - - // check that proposed certificate is present - proposedCertificate, _ := queryProposedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.NotNil(t, proposedCertificate) - - // propose revocation of proposed root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} - -func TestHandler_ProposeRevokeX509RootCert_ProposedRevocationAlreadyExists(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // store another trustee - anotherTrustee := GenerateAccAddress() - setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - - // propose revocation of the same x509 root certificate again - proposeRevokeX509RootCert = types.NewMsgProposeRevokeX509RootCert( - anotherTrustee.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.Error(t, err) - require.True(t, pkitypes.ErrProposedCertificateRevocationAlreadyExists.Is(err)) -} - -func TestHandler_ProposeRevokeX509RootCert_ForNonRootCertificate(t *testing.T) { - setup := Setup(t) - - // store x509 root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - - // store x509 intermediate certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) - - // propose revocation of x509 intermediate certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.Error(t, err) - require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) -} - -func TestHandler_ApproveRevokeX509RootCert_ForNotEnoughApprovals(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // Add 1 more trustee (this will bring the total trustee's to 4) - anotherTrustee := GenerateAccAddress() - setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // approve - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.NoError(t, err) - - // query and check proposed certificate revocation - proposedRevocation, _ := queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) - require.Equal(t, testconstants.RootSubject, proposedRevocation.Subject) - require.Equal(t, testconstants.RootSubjectKeyID, proposedRevocation.SubjectKeyId) - require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee1.String())) - require.True(t, proposedRevocation.HasRevocationFrom(setup.Trustee2.String())) - - // check that approved certificate still exists - certificate, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.NotNil(t, certificate) - - // check that revoked certificate does not exist - _, err = queryRevokedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificate key stays registered - require.True(t, - setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) -} - -func TestHandler_ApproveRevokeX509RootCert_ForEnoughApprovals(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // get certificate for further comparison - certificateBeforeRevocation, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.NotNil(t, certificateBeforeRevocation) - - // approve - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.NoError(t, err) - - // check that proposed certificate revocation does not exist anymore - _, err = queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that approved certificate does not exist anymore - _, err = queryApprovedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // query and check revoked certificate - revokedCertificate, _ := querySingleRevokedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Equal(t, certificateBeforeRevocation, revokedCertificate) - - // check that unique certificate key stays registered - require.True(t, - setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) -} - -func TestHandler_ApproveRevokeX509RootCert_BySerialNumber(t *testing.T) { - setup := Setup(t) - - rootCertOpt := &rootCertOptions{ - pemCert: testconstants.RootCertWithSameSubjectAndSKID1, - subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, - subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, - info: testconstants.Info, - vid: testconstants.Vid, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOpt) - rootCertOpt.pemCert = testconstants.RootCertWithSameSubjectAndSKID2 - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOpt) - rootSubject := rootCertOpt.subject - rootSubjectKeyID := rootCertOpt.subjectKeyID - // Add an intermediate certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID1) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - intermediateSubject := testconstants.IntermediateCertWithSameSubjectAndSKIDSubject - intermediateSubjectKeyID := testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID - - // get certificates for further comparison - certsBeforeRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.NotNil(t, certsBeforeRevocation) - require.Equal(t, 2, len(certsBeforeRevocation)) - require.Equal(t, 3, len(certsBeforeRevocation[0].Certs)+len(certsBeforeRevocation[1].Certs)) - - // propose revocation of root certificate with serial number "1" - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), rootSubject, rootSubjectKeyID, "1", false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // approve - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), rootSubject, rootSubjectKeyID, "1", testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.NoError(t, err) - - // check that proposed certificate revocation does not exist anymore - _, err = queryProposedCertificateRevocation(setup, "1") - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that only two approved certificates exists(root and child certificates) - rootCerts, _ := queryApprovedRootCertificates(setup, rootSubject, rootSubjectKeyID) - require.Equal(t, 1, len(rootCerts)) - require.Equal(t, "2", rootCerts[0].SerialNumber) - certificates, err := queryApprovedCertificates(setup, intermediateSubject, intermediateSubjectKeyID) - require.NoError(t, err) - require.Equal(t, 1, len(certificates.Certs)) - - // query and check revoked certificate - revokedCertificate, _ := querySingleRevokedCertificate(setup, rootSubject, rootSubjectKeyID) - require.NotNil(t, revokedCertificate) - require.Equal(t, "1", revokedCertificate.SerialNumber) - - // propose revocation of root certificate with serial number "2" - proposeRevokeX509RootCert = types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), rootSubject, rootSubjectKeyID, "2", true, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // approve - approveRevokeX509RootCert = types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), rootSubject, rootSubjectKeyID, "2", testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.NoError(t, err) - - // check that proposed certificate revocation does not exist anymore - _, err = queryProposedCertificateRevocation(setup, "2") - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that approved certificates does not exist anymore - certsAfterRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.Equal(t, 0, len(certsAfterRevocation)) - certsAfterRevocationBySubjectID := setup.Keeper.GetAllApprovedCertificatesBySubjectKeyID(setup.Ctx) - require.Equal(t, 0, len(certsAfterRevocationBySubjectID)) - - // query all revoked certificates - allRevokedCerts, _ := queryAllRevokedCertificates(setup) - require.Equal(t, 2, len(allRevokedCerts)) - - // query and check revoked root certificates - revokedCerts, _ := queryRevokedCertificates(setup, rootSubject, rootSubjectKeyID) - require.Equal(t, 2, len(revokedCerts.Certs)) - require.Equal(t, rootSubject, revokedCerts.Subject) - require.Equal(t, rootSubjectKeyID, revokedCerts.SubjectKeyId) - // query and check revoked intermediate certificate - revokedCerts, _ = queryRevokedCertificates(setup, intermediateSubject, intermediateSubjectKeyID) - require.Equal(t, 1, len(revokedCerts.Certs)) - require.Equal(t, intermediateSubject, revokedCerts.Subject) - require.Equal(t, intermediateSubjectKeyID, revokedCerts.SubjectKeyId) -} - -func TestHandler_ApproveRevokeX509RootCert_ByNotTrustee(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - for _, role := range []dclauthtypes.AccountRole{ - dclauthtypes.Vendor, - dclauthtypes.CertificationCenter, - dclauthtypes.NodeAdmin, - } { - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) - - // approve - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - accAddress.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) - } -} - -func TestHandler_ApproveRevokeX509RootCert_ProposedRevocationDoesNotExist(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // approve revocation of x509 root certificate - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) - _, err := setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.Error(t, err) - require.True(t, pkitypes.ErrProposedCertificateRevocationDoesNotExist.Is(err)) -} - -func TestHandler_ApproveRevokeX509RootCert_Twice(t *testing.T) { - setup := Setup(t) - - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // approve revocation by the same trustee - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) -} - -//nolint:funlen -func TestHandler_ApproveRevokeX509RootCert_ForTree(t *testing.T) { - setup := Setup(t) - - // add root x509 certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // add intermediate x509 certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // add leaf x509 certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) - _, err = setup.Handler(setup.Ctx, addLeafX509Cert) - require.NoError(t, err) - - // propose revocation of x509 root certificate - proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, "", true, testconstants.Info) - _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) - require.NoError(t, err) - - // approve - approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, "", testconstants.Info) - _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) - require.NoError(t, err) - - // check that root, intermediate and leaf certificates have been revoked - allRevokedCertificates, _ := queryAllRevokedCertificates(setup) - require.Equal(t, 3, len(allRevokedCertificates)) - require.Equal(t, testconstants.LeafSubject, allRevokedCertificates[0].Subject) - require.Equal(t, testconstants.LeafSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) - require.Equal(t, 1, len(allRevokedCertificates[0].Certs)) - require.Equal(t, testconstants.LeafCertPem, allRevokedCertificates[0].Certs[0].PemCert) - require.Equal(t, testconstants.RootSubject, allRevokedCertificates[1].Subject) - require.Equal(t, testconstants.RootSubjectKeyID, allRevokedCertificates[1].SubjectKeyId) - require.Equal(t, 1, len(allRevokedCertificates[1].Certs)) - require.Equal(t, testconstants.RootCertPem, allRevokedCertificates[1].Certs[0].PemCert) - require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[2].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[2].SubjectKeyId) - require.Equal(t, 1, len(allRevokedCertificates[2].Certs)) - require.Equal(t, testconstants.IntermediateCertPem, allRevokedCertificates[2].Certs[0].PemCert) - - // check that no certificates stays approved - allApprovedCertificates, err := queryAllApprovedCertificates(setup) - require.NoError(t, err) - require.Equal(t, 0, len(allApprovedCertificates)) - - // check that no proposed certificate revocations exist - allProposedCertificateRevocations, err := queryAllProposedCertificateRevocations(setup) - require.NoError(t, err) - require.Equal(t, 0, len(allProposedCertificateRevocations)) - - // check that no child certificate identifiers are registered for revoked root certificate - rootCertChildren, err := queryChildCertificates( - setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, rootCertChildren) - - // check that no child certificate identifiers are registered for revoked intermediate certificate - intermediateCertChildren, err := queryChildCertificates( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, intermediateCertChildren) - - // check that no child certificate identifiers are registered for revoked leaf certificate - leafCertChildren, err := queryChildCertificates( - setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - require.Nil(t, leafCertChildren) -} - -func TestHandler_RevokeX509Cert(t *testing.T) { - setup := Setup(t) - - // store root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - - for _, role := range []dclauthtypes.AccountRole{ - dclauthtypes.Vendor, - dclauthtypes.CertificationCenter, - dclauthtypes.Trustee, - dclauthtypes.NodeAdmin, - } { - accAddress := GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) - - // add x509 certificate - addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) - - // get intermediate certificate by subject-key-id - certsBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(certsBySubjectKeyID)) - // get certificate for further comparison - certificateBeforeRevocation, _ := querySingleApprovedCertificate( - setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.NotNil(t, certificateBeforeRevocation) - - // revoke x509 certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( - accAddress.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "", false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) - require.NoError(t, err) - - // check that intermediate certificate has been revoked - allRevokedCertificates, _ := queryAllRevokedCertificates(setup) - require.Equal(t, 1, len(allRevokedCertificates)) - require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[0].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) - require.Equal(t, 1, len(allRevokedCertificates[0].Certs)) - require.Equal(t, *certificateBeforeRevocation, *allRevokedCertificates[0].Certs[0]) - - // check that root certificate stays approved - allApprovedCertificates, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 1, len(allApprovedCertificates)) - require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[0].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) - - // check that intermediate certificate removed from subject-key-id -> certs map - certsBySubjectKeyID, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 0, len(certsBySubjectKeyID)) - - // check that no proposed certificate revocations have been created - allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) - require.NoError(t, err) - require.Equal(t, 0, len(allProposedCertificateRevocations)) - - // check that child certificate identifiers list of issuer do not exist anymore - _, err = queryChildCertificates(setup, testconstants.IntermediateIssuer, testconstants.IntermediateAuthorityKeyID) - require.Error(t, err) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificate key stays registered - require.True(t, setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, - testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber)) - - // cleanup for next iteration - setup.Keeper.RemoveRevokedCertificates(setup.Ctx, - testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - setup.Keeper.RemoveUniqueCertificate(setup.Ctx, - testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber) - } -} - -func TestHandler_RevokeX509Cert_BySerialNumber(t *testing.T) { - setup := Setup(t) - // propose and approve x509 root certificate - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // Add two intermediate certificates - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - intermediateCertificate := intermediateCertificate(setup.Trustee1) - intermediateCertificate.SerialNumber = SerialNumber - setup.Keeper.AddApprovedCertificate(setup.Ctx, intermediateCertificate) - setup.Keeper.AddApprovedCertificateBySubjectKeyID(setup.Ctx, intermediateCertificate) - setup.Keeper.SetUniqueCertificate( - setup.Ctx, - uniqueCertificate(intermediateCertificate.Issuer, intermediateCertificate.SerialNumber), - ) - // Add a leaf certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) - _, err = setup.Handler(setup.Ctx, addLeafX509Cert) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - // get certificates for further comparison - allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.NotNil(t, allCerts) - require.Equal(t, 3, len(allCerts)) - require.Equal(t, 4, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) + // get certificate for further comparison + certificateBeforeRevocation, _ := querySingleApprovedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.NotNil(t, certificateBeforeRevocation) - // revoke only an intermediate certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber, false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) + // approve + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.NoError(t, err) // check that proposed certificate revocation does not exist anymore - _, err = queryProposedCertificateRevocation(setup, testconstants.IntermediateSerialNumber) + _, err = queryProposedCertificateRevocation(setup, testconstants.RootSerialNumber) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) - // check that only root, intermediate and leaf certificates exists - allCerts, _ = queryAllApprovedCertificates(setup) - require.Equal(t, 3, len(allCerts)) - require.Equal(t, 3, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, SerialNumber, intermediateCerts.Certs[0].SerialNumber) - leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Equal(t, 1, len(leafCerts.Certs)) - require.Equal(t, testconstants.LeafSerialNumber, leafCerts.Certs[0].SerialNumber) - - // query and check revoked certificate - revokedCertificate, _ := querySingleRevokedCertificate(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.NotNil(t, revokedCertificate) - require.Equal(t, testconstants.IntermediateSubject, revokedCertificate.Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCertificate.SubjectKeyId) - require.Equal(t, testconstants.IntermediateSerialNumber, revokedCertificate.SerialNumber) - - // revoke intermediate and leaf certificates - revokeX509Cert = types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, SerialNumber, true, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) - require.NoError(t, err) - - _, err = queryProposedCertificateRevocation(setup, testconstants.IntermediateSerialNumber) + // check that approved certificate does not exist anymore + _, err = queryApprovedCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) - // check that only root certificate exists - certsAfterRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.Equal(t, 1, len(certsAfterRevocation)) - require.Equal(t, 1, len(certsAfterRevocation[0].Certs)) - require.Equal(t, testconstants.RootSerialNumber, certsAfterRevocation[0].Certs[0].SerialNumber) - // query and check revoked certificate - revokedCerts, _ := queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 2, len(revokedCerts.Certs)) - require.Equal(t, testconstants.IntermediateSubject, revokedCerts.Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCerts.SubjectKeyId) + revokedCertificate, _ := querySingleRevokedCertificate(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + require.Equal(t, certificateBeforeRevocation, revokedCertificate) - // query and check revoked certificate - revokedCerts, _ = queryRevokedCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) - require.Equal(t, 1, len(revokedCerts.Certs)) - require.Equal(t, testconstants.LeafSubject, revokedCerts.Subject) - require.Equal(t, testconstants.LeafSubjectKeyID, revokedCerts.SubjectKeyId) + // check that unique certificate key stays registered + require.True(t, + setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootIssuer, testconstants.RootSerialNumber)) } -func TestHandler_RemoveX509Cert_BySubjectAndSKID(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_BySerialNumber(t *testing.T) { setup := Setup(t) - // propose and approve x509 root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.RootCertWithSameSubjectAndSKID1, - subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, - subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, - info: testconstants.Info, - vid: 65521, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // Add two intermediate certificates - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID1) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - addIntermediateX509Cert = types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID2) - _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // Add a leaf certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertWithSameSubjectAndSKID) - _, err = setup.Handler(setup.Ctx, addLeafX509Cert) - require.NoError(t, err) - - // get certificates for further comparison - allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.NotNil(t, allCerts) - require.Equal(t, 3, len(allCerts)) - require.Equal(t, 4, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) - - // remove all intermediate certificates but leave leaf certificate - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, - testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - "", - ) - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.NoError(t, err) - - // check that only root and leaf certificates exists - allCerts, _ = queryAllApprovedCertificates(setup) - require.Equal(t, 2, len(allCerts)) - require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) - _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - // check that unique certificates does not exists - found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) - require.Equal(t, false, found) - found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) - require.Equal(t, false, found) - - leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 1, len(leafCerts.Certs)) - require.Equal(t, testconstants.LeafCertWithSameSubjectAndSKIDSerialNumber, leafCerts.Certs[0].SerialNumber) -} -func TestHandler_RemoveX509Cert_BySerialNumber(t *testing.T) { - setup := Setup(t) - // propose and approve x509 root certificate - rootCertOptions := &rootCertOptions{ + rootCertOpt := &rootCertOptions{ pemCert: testconstants.RootCertWithSameSubjectAndSKID1, subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, info: testconstants.Info, - vid: 65521, + vid: testconstants.Vid, } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // Add two intermediate certificates again - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID1) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - addIntermediateX509Cert = types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID2) - _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // Add a leaf certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertWithSameSubjectAndSKID) - _, err = setup.Handler(setup.Ctx, addLeafX509Cert) - require.NoError(t, err) - - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 2, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, intermediateCerts.Certs[0].Subject) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) - - // remove intermediate certificate by serial number - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, - testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber, - ) - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.NoError(t, err) - - // check that only root, intermediate(with serial number 3) and leaf certificates exists - allCerts, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 3, len(allCerts)) - require.Equal(t, 3, len(allCerts[0].Certs)+len(allCerts[1].Certs)+len(allCerts[2].Certs)) - leafCerts, _ := queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 1, len(leafCerts.Certs)) - - intermediateCerts, _ = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, intermediateCerts.Certs[0].SerialNumber) - - // remove intermediate certificate by serial number and check that leaf cert is not removed - removeX509Cert = types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, - testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, - ) - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.NoError(t, err) - - allCerts, _ = queryAllApprovedCertificates(setup) - require.Equal(t, 2, len(allCerts)) - require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) - - _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificates does not exists - found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) - require.Equal(t, false, found) - found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) - require.Equal(t, false, found) - - leafCerts, _ = queryApprovedCertificates(setup, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 1, len(leafCerts.Certs)) -} + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOpt) + rootCertOpt.pemCert = testconstants.RootCertWithSameSubjectAndSKID2 + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOpt) + rootSubject := rootCertOpt.subject + rootSubjectKeyID := rootCertOpt.subjectKeyID -func TestHandler_RemoveX509Cert_RevokedAndApprovedCertificate(t *testing.T) { - setup := Setup(t) - // propose and approve x509 root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.RootCertWithSameSubjectAndSKID1, - subject: testconstants.RootCertWithSameSubjectAndSKIDSubject, - subjectKeyID: testconstants.RootCertWithSameSubjectAndSKIDSubjectKeyID, - info: testconstants.Info, - vid: 65521, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) // Add an intermediate certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID1) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // get certificates for further comparison - allCerts := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) - require.NotNil(t, allCerts) - require.Equal(t, 2, len(allCerts)) - require.Equal(t, 2, len(allCerts[0].Certs)+len(allCerts[1].Certs)) - - // revoke an intermediate certificate - revokeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, - testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber, - ) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) - require.NoError(t, err) - - // Add an intermediate certificate with new serial number - addIntermediateX509Cert = types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateWithSameSubjectAndSKID2) - _, err = setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, intermediateCerts.Certs[0].Subject) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) - require.Equal(t, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, intermediateCerts.Certs[0].SerialNumber) - - // remove an intermediate certificate - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, - testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID, - testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber, - ) - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.NoError(t, err) - - // check that only root and leaf certificates exists - allCerts, _ = queryAllApprovedCertificates(setup) - require.Equal(t, 1, len(allCerts)) - require.Equal(t, true, allCerts[0].Certs[0].IsRoot) - _, err = queryApprovedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - _, err = queryRevokedCertificates(setup, testconstants.IntermediateCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificates does not exists - found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID1SerialNumber) - require.Equal(t, false, found) - found = setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.RootCertWithSameSubjectAndSKIDSubject, testconstants.IntermediateCertWithSameSubjectAndSKID2SerialNumber) - require.Equal(t, false, found) -} - -func TestHandler_RemoveX509Cert_RevokedCertificate(t *testing.T) { - setup := Setup(t) - // propose and approve x509 root certificate - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.RootCertPem, - subject: testconstants.RootSubject, - subjectKeyID: testconstants.RootSubjectKeyID, - info: testconstants.Info, - vid: 65521, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - // Add two intermediate certificates again - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateWithSameSubjectAndSKID1) _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) require.NoError(t, err) - intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(intermediateCerts.Certs)) - require.Equal(t, testconstants.IntermediateSubject, intermediateCerts.Certs[0].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) - - // revoke intermediate certificate by serial number - revokeX509Cert := types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateSubject, - testconstants.IntermediateSubjectKeyID, - testconstants.IntermediateSerialNumber, - false, - testconstants.Info, - ) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) - require.NoError(t, err) - - _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - - revokedCerts, _ := queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(revokedCerts.Certs)) - require.Equal(t, testconstants.IntermediateSubject, revokedCerts.Certs[0].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, revokedCerts.Certs[0].SubjectKeyId) - - // remove intermediate certificate by serial number - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), - testconstants.IntermediateSubject, - testconstants.IntermediateSubjectKeyID, - testconstants.IntermediateSerialNumber, - ) - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.NoError(t, err) - - allCerts, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 1, len(allCerts)) - require.Equal(t, true, allCerts[0].Certs[0].IsRoot) - - _, err = queryApprovedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - _, err = queryRevokedCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) - require.Equal(t, codes.NotFound, status.Code(err)) - - // check that unique certificate does not exists - found := setup.Keeper.IsUniqueCertificatePresent(setup.Ctx, testconstants.IntermediateIssuer, testconstants.IntermediateSerialNumber) - require.Equal(t, false, found) -} - -func TestHandler_RemoveX509Cert_CertificateDoesNotExist(t *testing.T) { - setup := Setup(t) - - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber) - _, err := setup.Handler(setup.Ctx, removeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} - -func TestHandler_RemoveX509Cert_EmptyCertificatesList(t *testing.T) { - setup := Setup(t) - - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - - setup.Keeper.SetApprovedCertificates( - setup.Ctx, - types.ApprovedCertificates{ - Subject: testconstants.IntermediateSubject, - SubjectKeyId: testconstants.IntermediateSubjectKeyID, - }, - ) - - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "") - _, err := setup.Handler(setup.Ctx, removeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} - -func TestHandler_RemoveX509Cert_ByNotOwner(t *testing.T) { - setup := Setup(t) - - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) - require.NoError(t, err) - - anotherTrustee := GenerateAccAddress() - setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - - removeX509Cert := types.NewMsgRemoveX509Cert( - anotherTrustee.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "") - _, err = setup.Handler(setup.Ctx, removeX509Cert) - require.Error(t, err) - require.True(t, sdkerrors.ErrUnauthorized.Is(err)) -} - -func TestHandler_RemoveX509Cert_ForRootCertificate(t *testing.T) { - setup := Setup(t) - - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber) - _, err := setup.Handler(setup.Ctx, removeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) -} + intermediateSubject := testconstants.IntermediateCertWithSameSubjectAndSKIDSubject + intermediateSubjectKeyID := testconstants.IntermediateCertWithSameSubjectAndSKIDSubjectKeyID -func TestHandler_RemoveX509Cert_InvalidSerialNumber(t *testing.T) { - setup := Setup(t) + // get certificates for further comparison + certsBeforeRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.NotNil(t, certsBeforeRevocation) + require.Equal(t, 2, len(certsBeforeRevocation)) + require.Equal(t, 3, len(certsBeforeRevocation[0].Certs)+len(certsBeforeRevocation[1].Certs)) - rootCertOptions := createTestRootCertOptions() - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // propose revocation of root certificate with serial number "1" + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), rootSubject, rootSubjectKeyID, "1", false, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.NoError(t, err) - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) + // approve + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), rootSubject, rootSubjectKeyID, "1", testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.NoError(t, err) - removeX509Cert := types.NewMsgRemoveX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "invalid") - _, err = setup.Handler(setup.Ctx, removeX509Cert) + // check that proposed certificate revocation does not exist anymore + _, err = queryProposedCertificateRevocation(setup, "1") require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} -func TestHandler_RevokeX509RootCertsBySubjectKeyId(t *testing.T) { - setup := Setup(t) + require.Equal(t, codes.NotFound, status.Code(err)) - // add root certificates - rootCertOptions := &rootCertOptions{ - pemCert: testconstants.PAACertWithSameSubjectID1, - subject: testconstants.PAACertWithSameSubjectID1Subject, - subjectKeyID: testconstants.PAACertWithSameSubjectIDSubjectID, - info: testconstants.Info, - vid: testconstants.Vid, - } - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - rootCertOptions.pemCert = testconstants.PAACertWithSameSubjectID2 - rootCertOptions.subject = testconstants.PAACertWithSameSubjectID2Subject - proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // check that only two approved certificates exists(root and child certificates) + rootCerts, _ := queryApprovedRootCertificates(setup, rootSubject, rootSubjectKeyID) + require.Equal(t, 1, len(rootCerts)) + require.Equal(t, "2", rootCerts[0].SerialNumber) + certificates, err := queryApprovedCertificates(setup, intermediateSubject, intermediateSubjectKeyID) + require.NoError(t, err) + require.Equal(t, 1, len(certificates.Certs)) - // revoke certificate - revokeX509Cert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.PAACertWithSameSubjectID1Subject, testconstants.PAACertWithSameSubjectIDSubjectID, "", false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, revokeX509Cert) + // query and check revoked certificate + revokedCertificate, _ := querySingleRevokedCertificate(setup, rootSubject, rootSubjectKeyID) + require.NotNil(t, revokedCertificate) + require.Equal(t, "1", revokedCertificate.SerialNumber) + + // propose revocation of root certificate with serial number "2" + proposeRevokeX509RootCert = types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), rootSubject, rootSubjectKeyID, "2", true, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - aprRevokeX509Cert := types.NewMsgApproveRevokeX509RootCert( - setup.Trustee2.String(), testconstants.PAACertWithSameSubjectID1Subject, testconstants.PAACertWithSameSubjectIDSubjectID, "", testconstants.Info) - _, err = setup.Handler(setup.Ctx, aprRevokeX509Cert) + // approve + approveRevokeX509RootCert = types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), rootSubject, rootSubjectKeyID, "2", testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.NoError(t, err) - // check that root certificate has been revoked - approvedCertificates, _ := queryApprovedCertificates(setup, testconstants.PAACertWithSameSubjectID2Subject, testconstants.PAACertWithSameSubjectIDSubjectID) - require.Equal(t, 1, len(approvedCertificates.Certs)) - require.Equal(t, testconstants.PAACertWithSameSubjectID2Subject, approvedCertificates.Certs[0].Subject) - require.Equal(t, testconstants.PAACertWithSameSubjectIDSubjectID, approvedCertificates.SubjectKeyId) + // check that proposed certificate revocation does not exist anymore + _, err = queryProposedCertificateRevocation(setup, "2") + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) - certsBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.PAACertWithSameSubjectIDSubjectID) - require.Equal(t, 1, len(certsBySubjectKeyID)) - require.Equal(t, 1, len(certsBySubjectKeyID[0].Certs)) - require.Equal(t, testconstants.PAACertWithSameSubjectIDSubjectID, certsBySubjectKeyID[0].SubjectKeyId) - require.Equal(t, testconstants.PAACertWithSameSubjectID2Subject, certsBySubjectKeyID[0].Certs[0].Subject) + // check that approved certificates does not exist anymore + certsAfterRevocation := setup.Keeper.GetAllApprovedCertificates(setup.Ctx) + require.Equal(t, 0, len(certsAfterRevocation)) + certsAfterRevocationBySubjectID := setup.Keeper.GetAllApprovedCertificatesBySubjectKeyID(setup.Ctx) + require.Equal(t, 0, len(certsAfterRevocationBySubjectID)) - // check that no proposed certificate revocations have been created - allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) - require.NoError(t, err) - require.Equal(t, 0, len(allProposedCertificateRevocations)) + // query all revoked certificates + allRevokedCerts, _ := queryAllRevokedCertificates(setup) + require.Equal(t, 2, len(allRevokedCerts)) + + // query and check revoked root certificates + revokedCerts, _ := queryRevokedCertificates(setup, rootSubject, rootSubjectKeyID) + require.Equal(t, 2, len(revokedCerts.Certs)) + require.Equal(t, rootSubject, revokedCerts.Subject) + require.Equal(t, rootSubjectKeyID, revokedCerts.SubjectKeyId) + // query and check revoked intermediate certificate + revokedCerts, _ = queryRevokedCertificates(setup, intermediateSubject, intermediateSubjectKeyID) + require.Equal(t, 1, len(revokedCerts.Certs)) + require.Equal(t, intermediateSubject, revokedCerts.Subject) + require.Equal(t, intermediateSubjectKeyID, revokedCerts.SubjectKeyId) } -func TestHandler_RevokeX509CertRoot_CertificateDoesNotExistBySerialNumber(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_ByNotTrustee(t *testing.T) { setup := Setup(t) + // propose and approve x509 root certificate rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // revoke x509 certificate - revokeX509Cert := types.NewMsgProposeRevokeX509RootCert( - setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, "invalid", false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, revokeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) -} -func TestHandler_RevokeX509Cert_CertificateDoesNotExist(t *testing.T) { - setup := Setup(t) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.NoError(t, err) - // revoke x509 certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, revokeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) + for _, role := range []dclauthtypes.AccountRole{ + dclauthtypes.Vendor, + dclauthtypes.CertificationCenter, + dclauthtypes.NodeAdmin, + } { + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, 1) + + // approve + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + accAddress.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + } } -func TestHandler_RevokeX509Cert_CertificateDoesNotExistBySerialNumber(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_ProposedRevocationDoesNotExist(t *testing.T) { setup := Setup(t) + // propose and approve x509 root certificate rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // Add intermediate certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) - require.NoError(t, err) - - // revoke x509 certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "invalid", false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) + // approve revocation of x509 root certificate + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) + _, err := setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.Error(t, err) - require.True(t, pkitypes.ErrCertificateDoesNotExist.Is(err)) + require.True(t, pkitypes.ErrProposedCertificateRevocationDoesNotExist.Is(err)) } -func TestHandler_RevokeX509Cert_ForRootCertificate(t *testing.T) { +func TestHandler_ApproveRevokeX509RootCert_Twice(t *testing.T) { setup := Setup(t) // propose and approve x509 root certificate rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) - // revoke x509 root certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, false, testconstants.Info) - _, err := setup.Handler(setup.Ctx, revokeX509Cert) - require.Error(t, err) - require.True(t, pkitypes.ErrInappropriateCertificateType.Is(err)) -} - -func TestHandler_RevokeX509Cert_ByNotOwner(t *testing.T) { - setup := Setup(t) - - // store root certificate - rootCertificate := rootCertificate(setup.Trustee1) - setup.Keeper.AddApprovedCertificate(setup.Ctx, rootCertificate) - - // add x509 certificate by `setup.Trustee` - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) - _, err := setup.Handler(setup.Ctx, addX509Cert) + _, err := setup.Handler(setup.Ctx, proposeRevokeX509RootCert) require.NoError(t, err) - // store another account - anotherTrustee := GenerateAccAddress() - setup.AddAccount(anotherTrustee, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, 1) - - // revoke x509 certificate by another account - revokeX509Cert := types.NewMsgRevokeX509Cert( - anotherTrustee.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, testconstants.IntermediateSerialNumber, false, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) + // approve revocation by the same trustee + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, testconstants.RootSerialNumber, testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.Error(t, err) require.True(t, sdkerrors.ErrUnauthorized.Is(err)) } -func TestHandler_RevokeX509Cert_ForTree(t *testing.T) { +//nolint:funlen +func TestHandler_ApproveRevokeX509RootCert_ForTree(t *testing.T) { setup := Setup(t) // add root x509 certificate rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + // add intermediate x509 certificate - addIntermediateX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) + addIntermediateX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) _, err := setup.Handler(setup.Ctx, addIntermediateX509Cert) require.NoError(t, err) // add leaf x509 certificate - addLeafX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.LeafCertPem) + addLeafX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.LeafCertPem) _, err = setup.Handler(setup.Ctx, addLeafX509Cert) require.NoError(t, err) - // check that intermediate nd leaf certificates removed from subject-key-id -> certs map - certs, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 1, len(certs)) - certs, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.LeafSubjectKeyID) - require.Equal(t, 1, len(certs)) + // propose revocation of x509 root certificate + proposeRevokeX509RootCert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, "", true, testconstants.Info) + _, err = setup.Handler(setup.Ctx, proposeRevokeX509RootCert) + require.NoError(t, err) - // revoke x509 certificate - revokeX509Cert := types.NewMsgRevokeX509Cert( - setup.Trustee1.String(), testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID, "", true, testconstants.Info) - _, err = setup.Handler(setup.Ctx, revokeX509Cert) + // approve + approveRevokeX509RootCert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), testconstants.RootSubject, testconstants.RootSubjectKeyID, "", testconstants.Info) + _, err = setup.Handler(setup.Ctx, approveRevokeX509RootCert) require.NoError(t, err) - // check that intermediate and leaf certificates have been revoked + // check that root, intermediate and leaf certificates have been revoked allRevokedCertificates, _ := queryAllRevokedCertificates(setup) - require.Equal(t, 2, len(allRevokedCertificates)) + require.Equal(t, 3, len(allRevokedCertificates)) require.Equal(t, testconstants.LeafSubject, allRevokedCertificates[0].Subject) require.Equal(t, testconstants.LeafSubjectKeyID, allRevokedCertificates[0].SubjectKeyId) require.Equal(t, 1, len(allRevokedCertificates[0].Certs)) require.Equal(t, testconstants.LeafCertPem, allRevokedCertificates[0].Certs[0].PemCert) - require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[1].Subject) - require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[1].SubjectKeyId) + require.Equal(t, testconstants.RootSubject, allRevokedCertificates[1].Subject) + require.Equal(t, testconstants.RootSubjectKeyID, allRevokedCertificates[1].SubjectKeyId) require.Equal(t, 1, len(allRevokedCertificates[1].Certs)) - require.Equal(t, testconstants.IntermediateCertPem, allRevokedCertificates[1].Certs[0].PemCert) - - // check that root certificate stays approved - allApprovedCertificates, _ := queryAllApprovedCertificates(setup) - require.Equal(t, 1, len(allApprovedCertificates)) - require.Equal(t, testconstants.RootSubject, allApprovedCertificates[0].Subject) - require.Equal(t, testconstants.RootSubjectKeyID, allApprovedCertificates[0].SubjectKeyId) - // check that root certificate(by subject key id) stays approved - allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.RootSubjectKeyID) - require.Equal(t, 1, len(allApprovedCertificates)) - require.Equal(t, testconstants.RootSubjectKeyID, allApprovedCertificates[0].SubjectKeyId) - // check that intermediate and leaf certificates removed from subject-key-id -> certs map - allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.IntermediateSubjectKeyID) - require.Equal(t, 0, len(allApprovedCertificates)) - allApprovedCertificates, _ = queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.LeafSubjectKeyID) + require.Equal(t, testconstants.RootCertPem, allRevokedCertificates[1].Certs[0].PemCert) + require.Equal(t, testconstants.IntermediateSubject, allRevokedCertificates[2].Subject) + require.Equal(t, testconstants.IntermediateSubjectKeyID, allRevokedCertificates[2].SubjectKeyId) + require.Equal(t, 1, len(allRevokedCertificates[2].Certs)) + require.Equal(t, testconstants.IntermediateCertPem, allRevokedCertificates[2].Certs[0].PemCert) + + // check that approved certs list is empty + allApprovedCertificates, err := queryAllApprovedCertificates(setup) + require.NoError(t, err) require.Equal(t, 0, len(allApprovedCertificates)) - // check that no proposed certificate revocations have been created - allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) + // check that no proposed certificate revocations exist + allProposedCertificateRevocations, err := queryAllProposedCertificateRevocations(setup) require.NoError(t, err) require.Equal(t, 0, len(allProposedCertificateRevocations)) - // check that no child certificate identifiers are now registered for root certificate - _, err = queryChildCertificates(setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) + // check that no child certificate identifiers are registered for revoked root certificate + rootCertChildren, err := queryChildCertificates( + setup, testconstants.RootSubject, testconstants.RootSubjectKeyID) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, rootCertChildren) // check that no child certificate identifiers are registered for revoked intermediate certificate - _, err = queryChildCertificates(setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) + intermediateCertChildren, err := queryChildCertificates( + setup, testconstants.IntermediateSubject, testconstants.IntermediateSubjectKeyID) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, intermediateCertChildren) // check that no child certificate identifiers are registered for revoked leaf certificate - _, err = queryChildCertificates(setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) + leafCertChildren, err := queryChildCertificates( + setup, testconstants.LeafSubject, testconstants.LeafSubjectKeyID) require.Error(t, err) require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, leafCertChildren) +} + +func TestHandler_RevokeX509RootCertsBySubjectKeyId(t *testing.T) { + setup := Setup(t) + + // add root certificates + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.PAACertWithSameSubjectID1, + subject: testconstants.PAACertWithSameSubjectID1Subject, + subjectKeyID: testconstants.PAACertWithSameSubjectIDSubjectID, + info: testconstants.Info, + vid: testconstants.Vid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + rootCertOptions.pemCert = testconstants.PAACertWithSameSubjectID2 + rootCertOptions.subject = testconstants.PAACertWithSameSubjectID2Subject + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + // revoke certificate + revokeX509Cert := types.NewMsgProposeRevokeX509RootCert( + setup.Trustee1.String(), testconstants.PAACertWithSameSubjectID1Subject, testconstants.PAACertWithSameSubjectIDSubjectID, "", false, testconstants.Info) + _, err := setup.Handler(setup.Ctx, revokeX509Cert) + require.NoError(t, err) + + aprRevokeX509Cert := types.NewMsgApproveRevokeX509RootCert( + setup.Trustee2.String(), testconstants.PAACertWithSameSubjectID1Subject, testconstants.PAACertWithSameSubjectIDSubjectID, "", testconstants.Info) + _, err = setup.Handler(setup.Ctx, aprRevokeX509Cert) + require.NoError(t, err) + + // check that root certificate has been revoked + approvedCertificates, _ := queryApprovedCertificates(setup, testconstants.PAACertWithSameSubjectID2Subject, testconstants.PAACertWithSameSubjectIDSubjectID) + require.Equal(t, 1, len(approvedCertificates.Certs)) + require.Equal(t, testconstants.PAACertWithSameSubjectID2Subject, approvedCertificates.Certs[0].Subject) + require.Equal(t, testconstants.PAACertWithSameSubjectIDSubjectID, approvedCertificates.SubjectKeyId) + + certsBySubjectKeyID, _ := queryAllApprovedCertificatesBySubjectKeyID(setup, testconstants.PAACertWithSameSubjectIDSubjectID) + require.Equal(t, 1, len(certsBySubjectKeyID)) + require.Equal(t, 1, len(certsBySubjectKeyID[0].Certs)) + require.Equal(t, testconstants.PAACertWithSameSubjectIDSubjectID, certsBySubjectKeyID[0].SubjectKeyId) + require.Equal(t, testconstants.PAACertWithSameSubjectID2Subject, certsBySubjectKeyID[0].Certs[0].Subject) + + // check that no proposed certificate revocations have been created + allProposedCertificateRevocations, _ := queryAllProposedCertificateRevocations(setup) + require.NoError(t, err) + require.Equal(t, 0, len(allProposedCertificateRevocations)) } func TestHandler_RejectX509RootCert_TwoRejectApprovalsAreNeeded(t *testing.T) { @@ -2706,6 +1566,16 @@ func createTestRootCertOptions() *rootCertOptions { } } +func createRootWithVidOptions() *rootCertOptions { + return &rootCertOptions{ + pemCert: testconstants.RootCertWithVid, + info: testconstants.Info, + subject: testconstants.RootCertWithVidSubject, + subjectKeyID: testconstants.RootCertWithVidSubjectKeyID, + vid: testconstants.RootCertWithVidVid, + } +} + func createPAACertWithNumericVidOptions() *rootCertOptions { return &rootCertOptions{ pemCert: testconstants.PAACertWithNumericVid, @@ -2990,8 +1860,12 @@ func TestHandler_AssignVid_ForNonRootCertificate(t *testing.T) { rootCertOptions := createTestRootCertOptions() proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + // Add vendor account + vendorAccAddress := GenerateAccAddress() + setup.AddAccount(vendorAccAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.Vid) + // add x509 intermediate certificate - addX509Cert := types.NewMsgAddX509Cert(setup.Trustee1.String(), testconstants.IntermediateCertPem) + addX509Cert := types.NewMsgAddX509Cert(vendorAccAddress.String(), testconstants.IntermediateCertPem) _, err := setup.Handler(setup.Ctx, addX509Cert) require.NoError(t, err) diff --git a/x/pki/keeper/approved_certificates.go b/x/pki/keeper/approved_certificates.go index 0b6c7a869..20fa5215d 100644 --- a/x/pki/keeper/approved_certificates.go +++ b/x/pki/keeper/approved_certificates.go @@ -41,22 +41,6 @@ func (k Keeper) GetApprovedCertificates( return val, true } -func (k Keeper) GetApprovedCertificateBySerialNumber( - ctx sdk.Context, - subject string, - subjectKeyID string, - serialNumber string, -) (val types.Certificate, found bool) { - certs, found := k.GetApprovedCertificates(ctx, subject, subjectKeyID) - if !found { - return val, false - } - - cert, found := findCertificate(serialNumber, &certs.Certs) - - return *cert, found -} - // RemoveApprovedCertificates removes a approvedCertificates from the store. func (k Keeper) RemoveApprovedCertificates( ctx sdk.Context, diff --git a/x/pki/keeper/keeper.go b/x/pki/keeper/keeper.go index 51a61c4a2..85c1ae684 100644 --- a/x/pki/keeper/keeper.go +++ b/x/pki/keeper/keeper.go @@ -50,3 +50,29 @@ func (k Keeper) CertificateApprovalsCount(ctx sdk.Context, authKeeper types.Dcla func (k Keeper) CertificateRejectApprovalsCount(ctx sdk.Context, authKeeper types.DclauthKeeper) int { return authKeeper.CountAccountsWithRole(ctx, authTypes.Trustee) - k.CertificateApprovalsCount(ctx, authKeeper) + 1 } + +func (k Keeper) EnsureVidMatches(ctx sdk.Context, owner string, signer string) error { + // get signer VID + signerAddr, err := sdk.AccAddressFromBech32(signer) + if err != nil { + return pkitypes.NewErrInvalidAddress(err) + } + + signerAccount, _ := k.dclauthKeeper.GetAccountO(ctx, signerAddr) + signerVid := signerAccount.VendorID + + // get owner VID + ownerAddr, err := sdk.AccAddressFromBech32(owner) + if err != nil { + return pkitypes.NewErrInvalidAddress(err) + } + + ownerAccount, _ := k.dclauthKeeper.GetAccountO(ctx, ownerAddr) + ownerVid := ownerAccount.VendorID + + if signerVid != ownerVid { + return pkitypes.NewErrUnauthorizedCertVendor(ownerVid) + } + + return nil +} diff --git a/x/pki/keeper/msg_server_add_noc_x_509_cert.go b/x/pki/keeper/msg_server_add_noc_x_509_cert.go index f65162376..7eb9ae6d5 100644 --- a/x/pki/keeper/msg_server_add_noc_x_509_cert.go +++ b/x/pki/keeper/msg_server_add_noc_x_509_cert.go @@ -62,11 +62,7 @@ func (k msgServer) AddNocX509Cert(goCtx context.Context, msg *types.MsgAddNocX50 // signer VID must be same as VID of existing certificates if accountVid != existingCertificate.Vid { - return nil, pkitypes.NewErrExistingCertVidNotEqualAccountVid( - x509Certificate.Subject, - x509Certificate.SubjectKeyID, - existingCertificate.Vid, - ) + return nil, pkitypes.NewErrUnauthorizedCertVendor(existingCertificate.Vid) } } // Valid certificate chain must be built for new certificate @@ -86,7 +82,7 @@ func (k msgServer) AddNocX509Cert(goCtx context.Context, msg *types.MsgAddNocX50 } // Check VID scoping if nocRootCert.Vid != accountVid { - return nil, pkitypes.NewErrAccountVidNotEqualToCertVid(accountVid, nocRootCert.Vid) + return nil, pkitypes.NewErrRootCertVidNotEqualToAccountVid(accountVid, nocRootCert.Vid) } // create new certificate diff --git a/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go b/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go index 33f6a7fd8..813b22e83 100644 --- a/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go +++ b/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go @@ -68,11 +68,7 @@ func (k msgServer) AddNocX509RootCert(goCtx context.Context, msg *types.MsgAddNo // signer VID must be same as VID of existing certificates if signerVid != existingCertificate.Vid { - return nil, pkitypes.NewErrExistingCertVidNotEqualAccountVid( - x509Certificate.Subject, - x509Certificate.SubjectKeyID, - existingCertificate.Vid, - ) + return nil, pkitypes.NewErrUnauthorizedCertVendor(existingCertificate.Vid) } } diff --git a/x/pki/keeper/msg_server_add_x_509_cert.go b/x/pki/keeper/msg_server_add_x_509_cert.go index 962095f39..08204c66e 100644 --- a/x/pki/keeper/msg_server_add_x_509_cert.go +++ b/x/pki/keeper/msg_server_add_x_509_cert.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/x509" ) @@ -13,6 +14,16 @@ import ( func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) (*types.MsgAddX509CertResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + signerAddr, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, pkitypes.NewErrInvalidAddress(err) + } + + // check if signer has vendor role + if !k.dclauthKeeper.HasRole(ctx, signerAddr, dclauthtypes.Vendor) { + return nil, pkitypes.NewErrUnauthorizedRole("MsgAddX509Cert", dclauthtypes.Vendor) + } + // decode pem certificate x509Certificate, err := x509.DecodeX509Certificate(msg.Cert) if err != nil { @@ -21,10 +32,7 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) // fail if certificate is self-signed if x509Certificate.IsSelfSigned() { - return nil, pkitypes.NewErrInappropriateCertificateType( - "Inappropriate Certificate Type: Passed certificate is self-signed, " + - "so it cannot be added to the system as a non-root certificate. " + - "To propose adding a root certificate please use `PROPOSE_ADD_X509_ROOT_CERT` transaction.") + return nil, pkitypes.NewErrNonRootCertificateSelfSigned() } // check if certificate with Issuer/Serial Number combination already exists @@ -50,45 +58,32 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) return nil, pkitypes.NewErrProvidedNotNocCertButExistingNoc(x509Certificate.Subject, x509Certificate.SubjectKeyID) } - // signer must be same as owner of existing certificates - if msg.Signer != existingCertificate.Owner { - return nil, pkitypes.NewErrUnauthorizedCertOwner(x509Certificate.Subject, x509Certificate.SubjectKeyID) + if err = k.EnsureVidMatches(ctx, existingCertificate.Owner, msg.Signer); err != nil { + return nil, err } } // Valid certificate chain must be built for new certificate - rootCert, err := k.verifyCertificate(ctx, x509Certificate) + decodedRootCert, err := k.verifyCertificate(ctx, x509Certificate) if err != nil { return nil, err } - // Check Root and Intermediate certs for VID scoping - rootVid, err := x509.GetVidFromSubject(x509.ToSubjectAsText(rootCert.SubjectAsText)) - if err != nil { - return nil, pkitypes.NewErrInvalidVidFormat(err) - } - childVid, err := x509.GetVidFromSubject(x509Certificate.SubjectAsText) - if err != nil { - return nil, pkitypes.NewErrInvalidVidFormat(err) - } - signerAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return nil, pkitypes.NewErrInvalidAddress(err) + + // get the full structure of the root certificate which contains the necessary fields for further validation + approvedRootCerts, _ := k.GetApprovedCertificates(ctx, decodedRootCert.Subject, decodedRootCert.SubjectKeyID) + if len(approvedRootCerts.Certs) == 0 { + return nil, pkitypes.NewErrRootCertificateDoesNotExist(decodedRootCert.Subject, decodedRootCert.SubjectKeyID) } + rootCert := approvedRootCerts.Certs[0] - signerAccount, _ := k.dclauthKeeper.GetAccountO(ctx, signerAddr) - accountVID := signerAccount.VendorID + // Root certificate must not be NOC + if rootCert.IsNoc { + return nil, pkitypes.NewErrProvidedNotNocCertButRootIsNoc() + } - if rootVid != 0 { - // If added under a VID scoped root CA: Intermediate cert must be also VID scoped to the same VID as a root one. - // Only a Vendor associated with this VID can add an intermediate certificate. So `rootVid == childVid == accountVID` - // condition must hold - if rootVid != childVid || rootVid != accountVID { - return nil, pkitypes.NewErrRootCertVidNotEqualToAccountVidOrCertVid(rootVid, accountVID, childVid) - } - // If added under a non-VID scoped root CA associated with a VID: Intermediate cert must be either VID scoped to the same VID, or non-VID scoped. - // Only a Vendor associated with this VID can add an intermediate certificate. - } else if childVid != 0 && childVid != accountVID { - return nil, pkitypes.NewErrAccountVidNotEqualToCertVid(accountVID, childVid) + // VID of account must match to VID of root and provided child certificates + if err = k.ensureVidMatches(ctx, rootCert, x509Certificate, signerAddr); err != nil { + return nil, err } // create new certificate @@ -101,7 +96,7 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) x509Certificate.Issuer, x509Certificate.AuthorityKeyID, rootCert.Subject, - rootCert.SubjectKeyID, + rootCert.SubjectKeyId, msg.Signer, ) @@ -131,3 +126,49 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) return &types.MsgAddX509CertResponse{}, nil } + +func (k msgServer) ensureVidMatches( + ctx sdk.Context, + rootCert *types.Certificate, + childCert *x509.Certificate, + signerAddr sdk.AccAddress, +) error { + // Check Root and Intermediate certs for VID scoping + rootVid, err := x509.GetVidFromSubject(x509.ToSubjectAsText(rootCert.SubjectAsText)) + if err != nil { + return pkitypes.NewErrInvalidVidFormat(err) + } + childVid, err := x509.GetVidFromSubject(childCert.SubjectAsText) + if err != nil { + return pkitypes.NewErrInvalidVidFormat(err) + } + + signerAccount, _ := k.dclauthKeeper.GetAccountO(ctx, signerAddr) + accountVID := signerAccount.VendorID + + if rootVid != 0 { //nolint:nestif + // If added under a VID scoped root CA: + // Child certificate must be also VID scoped to the same VID as a root one + if rootVid != childVid { + return pkitypes.NewErrRootCertVidNotEqualToCertVid(rootVid, childVid) + } + + // Only a Vendor associated with root certificate's VID can add an intermediate certificate + if rootVid != accountVID { + return pkitypes.NewErrRootCertVidNotEqualToAccountVid(rootVid, accountVID) + } + } else { + // If added under a non-VID scoped root CA: + // Child certificate must be either VID scoped to the same VID, or non-VID scoped. + if childVid != 0 && childVid != rootCert.Vid { + return pkitypes.NewErrRootCertVidNotEqualToCertVid(accountVID, childVid) + } + + // Only a Vendor associated with root certificate VID can add an intermediate certificate. + if rootCert.Vid != accountVID { + return pkitypes.NewErrRootCertVidNotEqualToAccountVid(rootCert.Vid, accountVID) + } + } + + return nil +} diff --git a/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go b/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go index 1ef8ff0cf..1b4ec2b54 100644 --- a/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go +++ b/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go @@ -73,7 +73,7 @@ func (k msgServer) ProposeAddX509RootCert(goCtx context.Context, msg *types.MsgP } // signer must be same as owner of existing certificates - if msg.Signer != existingCertificates.Certs[0].Owner { + if msg.Signer != existingCertificate.Owner { return nil, pkitypes.NewErrUnauthorizedCertOwner(x509Certificate.Subject, x509Certificate.SubjectKeyID) } } diff --git a/x/pki/keeper/msg_server_remove_x_509_cert.go b/x/pki/keeper/msg_server_remove_x_509_cert.go index 731b4c3e5..0c8fefb46 100644 --- a/x/pki/keeper/msg_server_remove_x_509_cert.go +++ b/x/pki/keeper/msg_server_remove_x_509_cert.go @@ -6,15 +6,27 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" ) func (k msgServer) RemoveX509Cert(goCtx context.Context, msg *types.MsgRemoveX509Cert) (*types.MsgRemoveX509CertResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + signerAddr, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, pkitypes.NewErrInvalidAddress(err) + } + + // check if signer has vendor role + if !k.dclauthKeeper.HasRole(ctx, signerAddr, dclauthtypes.Vendor) { + return nil, pkitypes.NewErrUnauthorizedRole("MsgRemoveX509Cert", dclauthtypes.Vendor) + } + aprCerts, foundApproved := k.GetApprovedCertificates(ctx, msg.Subject, msg.SubjectKeyId) revCerts, foundRevoked := k.GetRevokedCertificates(ctx, msg.Subject, msg.SubjectKeyId) - certificates := append(aprCerts.Certs, revCerts.Certs...) //nolint:gocritic + certificates := aprCerts.Certs + certificates = append(certificates, revCerts.Certs...) if len(certificates) == 0 { return nil, pkitypes.NewErrCertificateDoesNotExist(msg.Subject, msg.SubjectKeyId) } @@ -23,8 +35,8 @@ func (k msgServer) RemoveX509Cert(goCtx context.Context, msg *types.MsgRemoveX50 return nil, pkitypes.NewErrMessageRemoveRoot(msg.Subject, msg.SubjectKeyId) } - if msg.Signer != certificates[0].Owner { - return nil, pkitypes.NewErrMessageOnlyOwnerCanExecute("REVOKE_X509_CERT") + if err := k.EnsureVidMatches(ctx, certificates[0].Owner, msg.Signer); err != nil { + return nil, err } certID := types.CertificateIdentifier{ diff --git a/x/pki/keeper/msg_server_revoke_x_509_cert.go b/x/pki/keeper/msg_server_revoke_x_509_cert.go index b6cf42837..a8c32e53b 100644 --- a/x/pki/keeper/msg_server_revoke_x_509_cert.go +++ b/x/pki/keeper/msg_server_revoke_x_509_cert.go @@ -2,50 +2,50 @@ package keeper import ( "context" - "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" ) func (k msgServer) RevokeX509Cert(goCtx context.Context, msg *types.MsgRevokeX509Cert) (*types.MsgRevokeX509CertResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - certificates, found := k.GetApprovedCertificates(ctx, msg.Subject, msg.SubjectKeyId) - if !found { + signerAddr, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, pkitypes.NewErrInvalidAddress(err) + } + + // check if signer has vendor role + if !k.dclauthKeeper.HasRole(ctx, signerAddr, dclauthtypes.Vendor) { + return nil, pkitypes.NewErrUnauthorizedRole("MsgRevokeX509Cert", dclauthtypes.Vendor) + } + + certificates, _ := k.GetApprovedCertificates(ctx, msg.Subject, msg.SubjectKeyId) + if len(certificates.Certs) == 0 { return nil, pkitypes.NewErrCertificateDoesNotExist(msg.Subject, msg.SubjectKeyId) } if certificates.Certs[0].IsRoot { - return nil, pkitypes.NewErrInappropriateCertificateType( - fmt.Sprintf("Inappropriate Certificate Type: Certificate with subject=%v and subjectKeyID=%v "+ - "is a root certificate. To propose revocation of a root certificate please use "+ - "`PROPOSE_REVOKE_X509_ROOT_CERT` transaction.", msg.Subject, msg.SubjectKeyId), - ) + return nil, pkitypes.NewErrMessageRemoveRoot(msg.Subject, msg.SubjectKeyId) } - if msg.Signer != certificates.Certs[0].Owner { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, - "Only owner can revoke certificate using `REVOKE_X509_CERT`", - ) + if err := k.EnsureVidMatches(ctx, certificates.Certs[0].Owner, msg.Signer); err != nil { + return nil, err } certIdentifier := types.CertificateIdentifier{ Subject: msg.Subject, SubjectKeyId: msg.SubjectKeyId, } - var certBySerialNumber *types.Certificate if msg.SerialNumber != "" { - certBySerialNumber, found = findCertificate(msg.SerialNumber, &certificates.Certs) + certBySerialNumber, found := findCertificate(msg.SerialNumber, &certificates.Certs) if !found { return nil, pkitypes.NewErrCertificateBySerialNumberDoesNotExist(msg.Subject, msg.SubjectKeyId, msg.SerialNumber) } - } - if certBySerialNumber != nil { k._revokeX509Certificate(ctx, certBySerialNumber, certIdentifier, certificates) } else { k._revokeX509Certificates(ctx, certIdentifier, certificates)