dexter has submitted this change. ( https://gerrit.osmocom.org/c/onomondo-eim/+/43402?usp=email )
Change subject: rest_api_response_schema: re-structure REST API responses ......................................................................
rest_api_response_schema: re-structure REST API responses
The REST API responses are in parts inconsistent and the schema file lacks proper spec references in the description fields. Also in some places we mix proprietary error codes with return codes from SGP.32, which may lead to unexpected effects in case the SGP.32 ASN.1 spec changes.
With this patch we clean up those remaining shortcomings, in particular the following:
- Add a spec reference to each non-proprietary field - No longer mix SGP.32 error codes with proprietary error codes - Rename procedureError to eimProcedureError and make sure all possible error codes appear in the JSON schema properly. - Add dedicated error fields for each SGP.32 error code, so that the REST API user gets more detailed information in the error case - Restructure profileInstallationResult also return AID and SimaResponse, also add an profileInstallationError field which returns BppCommandId, ErrorReason and SimaResponse so that a REST API user has a chance to debug profile installation issues. - Orient the layout of result and error responses closer to the SGP.32 ASN.1 specification. - Do not specify the error codes in the JSON schema file to avoid unexpected problems when SGP.32 adds new error code. A spec reference in the field description should be sufficient.
Change-Id: I16cc063c185727e1b30f26d656bd15154504b087 Related: SYS#8100 --- M doc/build.md M doc/database.md M priv/rest_api_response_schema.json M src/esipa_asn1_handler.erl M src/esipa_asn1_handler_utils.erl M src/esipa_asn1_http_handler.erl M src/esipa_json_handler.erl M src/esipa_json_http_handler.erl M src/esipa_rest_utils.erl M src/mnesia_db.erl M src/mnesia_db_euicc.erl M src/mnesia_db_rest.erl M src/mnesia_db_work.erl 13 files changed, 388 insertions(+), 456 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified dexter: Looks good to me, approved
diff --git a/doc/build.md b/doc/build.md index 5bb08af..cab53a6 100644 --- a/doc/build.md +++ b/doc/build.md @@ -222,16 +222,16 @@ done.
* The timeout `rest_timeout_stuck` guards against stuck orders. Orders may get stuck due to communication errors between - SMDP+ or IPAd. When a procedure is stuck for too long it gets marked as done and an appropriate `procedureError` code - is communicated to the REST API user. Since a procedure usually won't take more than a few minutes (usually below one - minute) 300 sec. would be a good compromise here. + SMDP+ or IPAd. When a procedure is stuck for too long it gets marked as done and an appropriate `eimProcedureError` + code is communicated to the REST API user. Since a procedure usually won't take more than a few minutes (usually + below one minute) 300 sec. would be a good compromise here.
* The timeout `rest_timeout_noshow` guards against IPAd/eUICCs that fail to show up. When an order is placed the IPAd is expected to poll the eIM within a reasonable amount of time. When the IPAd fails to poll for some reason, the - order gets marked as done and an appropriate 'procedureError' code is communicated to the REST API user. Usually the - polling is triggered through some side channel or the polling happens periodically. Depending on the situation the - timeout may be set to several hours or even days. In any case it should not be lower than `rest_timeout_stuck` for - obvious reasons. A recommended timeout value would be 1800 (30 min). + order gets marked as done and an appropriate 'eimProcedureError' code is communicated to the REST API user. Usually + the polling is triggered through some side channel or the polling happens periodically. Depending on the situation + the timeout may be set to several hours or even days. In any case it should not be lower than `rest_timeout_stuck` + for obvious reasons. A recommended timeout value would be 1800 (30 min).
* The timeout `rest_timeout_expired` guards against careless REST API users. As mentioned already, the REST API user is expected to carefully monitor his orders and delete them on his own responsibility. However, it may be that a REST diff --git a/doc/database.md b/doc/database.md index 8ae5471..3b066b7 100644 --- a/doc/database.md +++ b/doc/database.md @@ -137,4 +137,4 @@ in progress (`status` = `work`) are terminated. Since the `work` table is kept in RAM only it will naturally lose its contents. When onomondo-eim restarts it will go through the `rest` table to set the status of each rest resource that still has its `status` set to `work` to `done`. To make the REST API user aware of the situation an appropriate -`procedureError` code is set as well (`abortedOrder`). +`eimProcedureError` code is set as well (`abortedOrder`). diff --git a/priv/rest_api_response_schema.json b/priv/rest_api_response_schema.json index 6542215..f8df3f7 100644 --- a/priv/rest_api_response_schema.json +++ b/priv/rest_api_response_schema.json @@ -31,135 +31,92 @@ "anyOf": [ { "enableResult": { - "description": "profile enable PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "iccidOrAidNotFound", - "profileNotInDisabledState", - "disallowedByPolicy", - "catBusy", - "rollbackNotAvailable", - "undefinedError" - ] + "description": "profile enable PSMO result, see also GSMA SGP.32, section 2.11.2.1 (EnableProfileResult)", + "type": "string" } }, { "disableResult": { - "description": "profile disable PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "iccidOrAidNotFound", - "profileNotInEnabledState", - "disallowedByPolicy", - "catBusy", - "undefinedError" - ] + "description": "profile disable PSMO result, see also GSMA SGP.32, section 2.11.2.1 (DisableProfileResult)", + "type": "string" } }, { "deleteResult": { - "description": "profile delete PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "iccidOrAidNotFound", - "profileNotInDisabledState", - "disallowedByPolicy", - "rollbackNotAvailable", - "returnFallbackProfile", - "undefinedError" - ] + "description": "profile delete PSMO result, see also GSMA SGP.32, section 2.11.2.1 (DeleteProfileResult)", + "type": "string" } }, { "listProfileInfoResult": { - "description": "listProfileInfoResult PSMO result, see also SGP32Definitions.asn1", - "type": "object", - "properties": { - "finalResult": { - "description": "overall status code to inform about success or failure", - "type": "string", - "enum": [ - "successResult", - "errorResult" - ] - }, - "profileInfoList": { - "description": "contains a list of installed profiles and their meta data, see also RSPDefinitions.asn1", - "type": "array", - "items": { - "type": "object", - "properties": { - "iccid": { - "description": "ICCID of the profile. (ICCID in nibble-swapped raw format, see also ETSI TS 102 221, section 13.2)", - "type": "string", - "pattern": "^[0-9A-F]{18,20}$" - }, - "isdpAid": { - "description": "AID of the ISDP (identifies a profile)", - "type": "string", - "pattern": "^[0-9A-F]{2,32}$" - }, - "profileState": { - "description": "usage state of the prifle", - "type": "string", - "enum": [ - "disabled", - "enabled" - ] - }, - "profileNickname": { - "description": "human readable nickname name of the profile", - "type": "string" - }, - "serviceProviderName": { - "description": "human readable name of the related service provider", - "type": "string" - }, - "profileName": { - "description": "human readable name of the profile", - "type": "string" - }, - "iconType": { - "description": "graphics format in which the profile icon is supplied", - "type": "string" - }, - "icon": { - "description": "icon graphic", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "profileClass": { - "description": "0=test, 1=provisioning, 2=operational", - "type": "integer" - }, - "ecallIndication": { - "description": "indicates if the profile is an Emergency Profile", - "type": "boolean" - }, - "fallbackAttribute": { - "description": "indicates a Fallback Profile", - "type": "boolean" - }, - "fallbackAllowed": { - "description": "indicates if Fallback is authorized by the Profile Owner", - "type": "boolean" - } - } + "description": "contains a list of installed profiles and their meta data, see also GSMA SGP.32, section 4.4 (ProfileInfo)", + "type": "array", + "items": { + "type": "object", + "properties": { + "iccid": { + "description": "ICCID of the profile. (ICCID in nibble-swapped raw format, see also ETSI TS 102 221, section 13.2)", + "type": "string", + "pattern": "^[0-9A-F]{18,20}$" + }, + "isdpAid": { + "description": "AID of the ISDP (identifies a profile)", + "type": "string", + "pattern": "^[0-9A-F]{2,32}$" + }, + "profileState": { + "description": "usage state of the prifle", + "type": "string", + "enum": [ + "disabled", + "enabled" + ] + }, + "profileNickname": { + "description": "human readable nickname name of the profile", + "type": "string" + }, + "serviceProviderName": { + "description": "human readable name of the related service provider", + "type": "string" + }, + "profileName": { + "description": "human readable name of the profile", + "type": "string" + }, + "iconType": { + "description": "graphics format in which the profile icon is supplied", + "type": "string" + }, + "icon": { + "description": "icon graphic", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "profileClass": { + "description": "0=test, 1=provisioning, 2=operational", + "type": "integer" + }, + "ecallIndication": { + "description": "indicates if the profile is an Emergency Profile", + "type": "boolean" + }, + "fallbackAttribute": { + "description": "indicates a Fallback Profile", + "type": "boolean" + }, + "fallbackAllowed": { + "description": "indicates if Fallback is authorized by the Profile Owner", + "type": "boolean" } } }, - "required": [ - "finalResult" - ], "additionalProperties": false } }, { "getRATResult": { - "description": "getRAT (rules authorization table) PSMO result, see also RSPDefinitions.asn1", + "description": "getRAT (rules authorization table) PSMO result, see also GSMA SGP.22, section 5.7.22 (ProfilePolicyAuthorisationRule)", "type": "array", "items": { "type": "object", @@ -177,7 +134,7 @@ "type": "boolean" }, "allowedOperators": { - "description": "list of allowed operaters, see also GSMA SGP.22, section 2.9.2.1", + "description": "list of allowed operaters, see also GSMA SGP.22, section 2.8.1.2 (OperatorId)", "type": "array", "items": { "mccMnc": { @@ -219,213 +176,175 @@ }, { "configureImmediateEnableResult": { - "description": "configureImmediateEnableResult (automatic profile enabeling) PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "insufficientMemory", - "commandError", - "undefinedError" - ] - } - }, - { - "setFallbackAttributeResult": { - "description": "setFallbackAttributeResult PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "iccidOrAidNotFound", - "fallbackNotAllowed", - "fallbackProfileEnabled", - "undefinedError" - ] - } - }, - { - "unsetFallbackAttributeResult": { - "description": "unsetFallbackAttributeResult PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "noFallbackAttribute", - "fallbackProfileEnabled", - "commandError", - "undefinedError" - ] - } - }, - { - "setDefaultDpAddressResult": { - "description": "setDefaultDpAddressResult PSMO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "undefinedError" - ] + "description": "configureImmediateEnableResult (automatic profile enabeling) PSMO result, see also GSMA SGP.32, section 2.11.2.1 (ConfigureImmediateEnableResult)", + "type": "string" } }, { "addEimResult": { - "description": "addEimResult eCO result", + "description": "addEimResult eCO result, see also GSMA SGP.32, section 2.11.2.1 (AddEimResult)", "type": "object", "properties": { "addEimResultCode": { - "description": "overall status code to inform about success or failure", - "type": "string", - "enum": [ - "ok", - "insufficientMemory", - "associatedEimAlreadyExists", - "ciPKUnknown", - "invalidAssociationToken", - "counterValueOutOfRange", - "commandError", - "undefinedError", - "malformedResult" - ] + "description": "overall status code to inform about success or failure, see also GSMA SGP.32, section 2.11.2.1", + "type": "string" }, "associationToken": { "description": "resulting association token, see also GSMA SGP.32, section 2.11.1.1.1", "type": "integer" } }, - "required": [ - "addEimResultCode" - ], "additionalProperties": false } }, { "deleteEimResult": { - "description": "deleteEimResult eCO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "eimNotFound", - "lastEimDeleted", - "commandError", - "undefinedError" - ] + "description": "deleteEimResult eCO result, see also GSMA SGP.32, section 2.11.1.1.1 (DeleteEimResult)", + "type": "string" } }, { "updateEimResult": { - "description": "updateEimResult eCO result, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "eimNotFound", - "ciPKUnknown", - "counterValueOutOfRange", - "commandError", - "undefinedError" - ] + "description": "updateEimResult eCO result, see also GSMA SGP.32, section 2.11.1.1.1 (UpdateEimResult)", + "type": "string" } }, { "listEimResult": { - "description": "listEimResult eCO result, see also SGP32Definitions.asn1", - "type": "object", - "properties": { - "finalResult": { - "description": "overall status code to inform about success or failure", + "description": "listEimResult eCO result, see also GSMA SGP.32, section 2.11.1.1.1 (EimIdInfo)", + "type": "array", + "items": { + "eimId": { + "description": "eIM ID", + "type": "string" + }, + "eimIdType": { + "description": "specifies the type of the eIM ID", "type": "string", "enum": [ - "successResult", - "errorResult" - ] - }, - "eimIdList": { - "description": "list containing the IDs of all configured eIM servers", - "type": "array", - "items": { - "eimId": { - "description": "eIM ID", - "type": "string" - }, - "eimIdType": { - "description": "specifies the type of the eIM ID", - "type": "string", - "enum": [ - "eimIdTypeOid", - "eimIdTypeFqdn", - "eimIdTypeProprietary" - ] - } - }, - "required": [ - "eimId" + "eimIdTypeOid", + "eimIdTypeFqdn", + "eimIdTypeProprietary" ] } }, "required": [ - "finalResult" + "eimId" ], "additionalProperties": false } }, { "rollbackResult": { - "description": "Status code of the execution of a profile rollback maneuver, see also GSMA SGP.32, section 2.11.1.13 and SGP32Definitions.asn1", - "type": "string", - "enum": [ - "ok", - "undefinedError" - ] + "description": "Status code of the execution of a profile rollback maneuver, see also GSMA SGP.32, section 2.11.2.1 (RollbackProfileResult)", + "type": "string" + } + }, + { + "setFallbackAttributeResult": { + "description": "setFallbackAttributeResult PSMO result, see also GSMA SGP.32, section 2.11.2.1 (SetFallbackAttributeResult)", + "type": "string" + } + }, + { + "unsetFallbackAttributeResult": { + "description": "unsetFallbackAttributeResult PSMO result, see also GSMA SGP.32, section 2.11.2.1 (UnsetFallbackAttributeResult)", + "type": "string" } }, { "processingTerminated": { - "description": "Error code in case the eUICC has terminated the overall eUICC package execution, see also SGP32Definitions.asn1", - "type": "string", - "enum": [ - "resultSizeOverflow", - "unknownOrDamagedCommand", - "interruption", - "undefinedError" - ] + "description": "Error code in case the eUICC has terminated the overall eUICC package execution, see also GSMA SGP.32, section 2.11.2.1 (EuiccResultData->processingTerminated)", + "type": "string" } }, { - "notificationResult": { - "description": "Status code to indicate that an otherSignedNotification has been received", - "type": "string", - "enum": [ - "otherSignedNotification" - ] + "setDefaultDpAddressResult": { + "description": "setDefaultDpAddressResult PSMO result, see also GSMA SGP.32, section 2.11.2.1 (SetDefaultDpAddressResponse->setDefaultDpAddressResult)", + "type": "string" } }, { - "cancelSessionResult": { - "description": "Status code to indicate that the session has been canceled", - "type": "string", - "enum": [ - "ok", - "undefinedError" - ] + "euiccDataResult": { + "description": "contains the resulting eUICC data objects, see also SGP.32, section 2.11.2.2 (IpaEuiccData)", + "type": "object", + "properties": { + "defaultSmdpAddress": { + "description": "see GSMA SGP.32", + "type": "string" + }, + "euiccInfo1": { + "description": "ASN.1 encoded, see GSMA SGP.22", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "euiccInfo2": { + "description": "ASN.1 encoded, see GSMA SGP.22 and GSMA SGP.32", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "rootSmdsAddress": { + "description": "see GSMA SGP.32", + "type": "string" + }, + "associationToken": { + "description": "see GSMA SGP.32", + "type": "integer" + }, + "eumCertificate": { + "description": "ASN.1 encoded, see GSMA SGP.22", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "euiccCertificate": { + "description": "ASN.1 encoded, see GSMA SGP.22", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "ipaCapabilities": { + "description": "ASN.1 encoded, see GSMA SGP.32", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "deviceInfo": { + "description": "ASN.1 encoded, see GSMA SGP.32", + "type": "string", + "pattern": "^[0-9A-F].*$" + }, + "notificationsList": { + "description": "ASN.1 encoded, see GSMA SGP.32", + "type": "string", + "pattern": "^[0-9A-F].*$" + } + }, + "additionalProperties": false } }, { "profileInstallationResult": { - "description": "Final result of a profile download, see also SGP32Definitions.asn1", + "description": "Profile installation result (success)", "type": "object", "properties": { - "finalResult": { - "description": "overall status code to inform about succes or failure", - "enum": [ - "successResult", - "errorResult" - ] - }, "iccid": { "description": "ICCID of the profile. (ICCID in nibble-swapped raw format, see also ETSI TS 102 221, section 13.2)", "type": "string", "pattern": "^[0-9A-F]{18,20}$" + }, + "aid": { + "description": "AID of the profile. (ICCID in nibble-swapped raw format, see also ETSI TS 102 221, section 13.2)", + "type": "string", + "pattern": "^[0-9A-F]{5,16}$" + }, + "simaResponse": { + "description": "SIMA Response, see also TCA eUICC Profile Package: Interoperable Format, Technical Specificationsection, section 8.11", + "type": "string", + "pattern": "^[0-9A-F].*$" } }, "required": [ - "finalResult" + "iccid", + "aid", + "simaResponse" ], "additionalProperties": false } @@ -464,103 +383,119 @@ } }, { - "euiccDataResult": { - "description": "contains the result of an ipaEuiccDataRequest request (see also GSMA SGP.32, section 2.11.1.2)", + "cancelSessionReason": { + "description": "Status code to indicate that (and why) the session has been canceled, see also GSMA SGP.22, section 5.7.14 (CancelSessionReason)", + "type": "string" + } + }, + { + "euiccPackageError": { + "description": "indicates a problem with the processing of an eUICC package, see also GSMA SGP.32, section 2.11.2.1 (EuiccPackageErrorCode)", + "type": "string" + } + }, + { + "ipaEuiccDataError": { + "description": "indicates a problem with the retrieval of eUICC data, see also GSMA SGP.32, section 2.11.2.2 (IpaEuiccDataErrorCode)", + "type": "string" + } + }, + { + "eimPackageResultError": { + "description": "indicates a problem with the processing of an eIM package, see also GSMA SGP.32, section 6.3.2.7 (EimPackageResultErrorCode)", + "type": "string" + } + }, + { + "initiateAuthenticationError": { + "description": "indicates an eUICC/SM-DP+ authentication problem, see also GSMA SGP.32, section 6.3.2.1 (initiateAuthenticationErrorEsipa)", + "type": "string" + } + }, + { + "authenticateResponseError": { + "description": "indicates an eUICC/SM-DP+ authentication problem, see also GSMA SGP.22, section 5.7.13 (AuthenticateErrorCode)", + "type": "string" + } + }, + { + "authenticateClientError": { + "description": "indicates an eUICC/SM-DP+ authentication problem, see also GSMA SGP.32, section 6.3.2.2 (authenticateClientErrorEsipa)", + "type": "string" + } + }, + { + "downloadResponseError": { + "description": "indicates a profile download problem, see also GSMA SGP.22, section 5.7.5 (DownloadErrorCode)", + "type": "string" + } + }, + { + "getBoundProfilePackageError": { + "description": "indicates a profile download problem, see also GSMA SGP.23, section 6.3.2.3 (getBoundProfilePackageErrorEsipa)", + "type": "string" + } + }, + { + "cancelSessionResponseError": { + "description": "indicates a session cancellation problem, see also GSMA SGP.23, section 5.14.8 (CancelSessionResponse->cancelSessionResponseError)", + "type": "string" + } + }, + { + "profileInfoListError": { + "description": "indicates a problem during the collection of profile information, see also GSMA SGP.23, section 2.11.2.1 (ProfileInfoListError)", + "type": "string" + } + }, + { + "listEimError": { + "description": "indicates a problem during the collection of eIM information, see also GSMA SGP.23, section 2.11.2.1 (ListEimResult->listEimError)", + "type": "string" + } + }, + { + "profileInstallationError": { + "description": "Indicates a problem during Profile installation", "type": "object", "properties": { - "edrResult": { - "description": "status code of the execution of the ipaEuiccDataRequest", - "type": "string", - "enum": [ - "ok", - "incorrectTagList", - "euiccCiPKIdNotFound", - "undefinedError" - ] + "bppCommandId": { + "description": "Identifies the ES8+ function that has failed, see also GSMA SGP.22, section 2.5.6 and section 5.5", + "type": "string" }, - "euiccData": { - "description": "contains the resulting eUICC data objects", - "type": "object", - "properties": { - "defaultSmdpAddress": { - "description": "see GSMA SGP.32", - "type": "string" - }, - "euiccInfo1": { - "description": "ASN.1 encoded, see GSMA SGP.22", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "euiccInfo2": { - "description": "ASN.1 encoded, see GSMA SGP.22 and GSMA SGP.32", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "rootSmdsAddress": { - "description": "see GSMA SGP.32", - "type": "string" - }, - "associationToken": { - "description": "see GSMA SGP.32", - "type": "integer" - }, - "eumCertificate": { - "description": "ASN.1 encoded, see GSMA SGP.22", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "euiccCertificate": { - "description": "ASN.1 encoded, see GSMA SGP.22", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "ipaCapabilities": { - "description": "ASN.1 encoded, see GSMA SGP.32", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "deviceInfo": { - "description": "ASN.1 encoded, see GSMA SGP.32", - "type": "string", - "pattern": "^[0-9A-F].*$" - }, - "notificationsList": { - "description": "ASN.1 encoded, see GSMA SGP.32", - "type": "string", - "pattern": "^[0-9A-F].*$" - } - }, - "additionalProperties": false + "errorReason": { + "description": "Reason to narrow down what caused the error, see also GSMA SGP.22, section 2.5.6", + "type": "string" + }, + "simaResponse": { + "description": "SIMA Response, see also TCA eUICC Profile Package: Interoperable Format, Technical Specificationsection, section 8.11", + "type": "string", + "pattern": "^[0-9A-F].*$" } }, "required": [ - "edrResult" + "bppCommandId", + "errorReason", + "simaResponse" ], "additionalProperties": false } }, { - "procedureError": { - "description": "indicates a problem that lead to a termination of a procedure", + "eimProcedureError": { + "description": "indicates an eIM internal problem that lead to a termination of a procedure", "type": "string", - "enum": [ - "initiateAuthenticationError", - "authenticateResponseError", - "authenticateClientError", - "downloadResponseError", - "getBoundProfilePackageError", - "cancelSessionResponseError", - "handleNotificationError", - "euiccSignatureInvalid", - "undefinedError", - "badPsmo", - "badEco", - "badEdr", - "badState", - "badOrder", - "abortedOrder", - "stuckOrder", - "noshowOrder" + "enum": [ + "abortedOrder", + "stuckOrder", + "noshowOrder", + "badOrder", + "badSignature", + "badCounter", + "badEuiccResult", + "badState", + "badEid", + "undefinedError" ] } } diff --git a/src/esipa_asn1_handler.erl b/src/esipa_asn1_handler.erl index 3d0d6b0..df208cf 100644 --- a/src/esipa_asn1_handler.erl +++ b/src/esipa_asn1_handler.erl @@ -50,11 +50,8 @@ }, {initiateAuthenticationOkEsipa, InitAuthOkEsipa}; {initiateAuthenticationError, InitAuthErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, initiateAuthenticationError}]}], - EsipaReq - ), + Outcome = [{[{initiateAuthenticationError, InitAuthErr}]}], + ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq), {initiateAuthenticationErrorEsipa, InitAuthErr} end, {initiateAuthenticationResponseEsipa, EsipaResp}; @@ -76,11 +73,8 @@ authenticateServerResponse => {authenticateResponseOk, AuthRespOk} }}; {authenticateResponseError, AuthRespErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, authenticateResponseError}]}], - EsipaReq - ), + OutcomeEsipa = [{[{authenticateResponseError, AuthRespErr}]}], + ok = mnesia_db_work:finish(Pid, OutcomeEsipa, EsipaReq), {authenticateClientRequest, #{ transactionId => TransactionId, authenticateServerResponse => {authenticateResponseError, AuthRespErr} @@ -99,11 +93,8 @@ {authenticateClientOk, AuthClntRespEs9} -> {authenticateClientOkDPEsipa, AuthClntRespEs9}; {authenticateClientError, AuthClntErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, authenticateClientError}]}], - EsipaReq - ), + OutcomeEs9p = [{[{authenticateClientError, AuthClntErr}]}], + ok = mnesia_db_work:finish(Pid, OutcomeEs9p, EsipaReq), {authenticateClientErrorEsipa, AuthClntErr} end, {authenticateClientResponseEsipa, EsipaResp}; @@ -123,11 +114,9 @@ prepareDownloadResponse => {downloadResponseOk, DwnldRespOk} }}; {downloadResponseError, DwnldRespErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, downloadResponseError}]}], - EsipaReq - ), + DownloadErrorCode = maps:get(downloadErrorCode, DwnldRespErr), + OutcomeEsipa = [{[{downloadResponseError, DownloadErrorCode}]}], + ok = mnesia_db_work:finish(Pid, OutcomeEsipa, EsipaReq), {getBoundProfilePackageRequest, #{ transactionId => TransactionId, prepareDownloadResponse => {downloadResponseError, DwnldRespErr} @@ -148,11 +137,8 @@ % however, this eIM does not support the IPA capability minimizeEsipaBytes) {getBoundProfilePackageOkEsipa, GetBndPrflePkgOk}; {getBoundProfilePackageError, GetBndPrflePkgErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, getBoundProfilePackageError}]}], - EsipaReq - ), + OutcomeEs9p = [{[{getBoundProfilePackageError, GetBndPrflePkgErr}]}], + ok = mnesia_db_work:finish(Pid, OutcomeEs9p, EsipaReq), {getBoundProfilePackageErrorEsipa, GetBndPrflePkgErr} end, {getBoundProfilePackageResponseEsipa, EsipaResp}; @@ -172,11 +158,6 @@ cancelSessionResponse => {cancelSessionResponseOk, CancelSessionRespOk} }}; {cancelSessionResponseError, CancelSessionRespErr} -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, cancelSessionResponseError}]}], - EsipaReq - ), {cancelSessionRequestEs9, #{ transactionId => TransactionId, cancelSessionResponse => {cancelSessionResponseError, CancelSessionRespErr} @@ -221,25 +202,18 @@ % context but it will foward it to the SMDP+ anyway. case mnesia_db_work:bind(Pid, TransactionId) of ok -> - % A work item exists, foward the ProfileInstallationResult and make its contents - % available to the REST API user - case es9p_client:request_json(Es9Req, BaseUrl) of - {} -> - Outcome = esipa_rest_utils:profileInstallationResult_to_outcome( - PrfleInstRslt - ), - ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq); - _ -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, handleNotificationError}]}], - EsipaReq - ) - end; + % A related work item exists, make the notification contents available to the REST API user + Outcome = esipa_rest_utils:profileInstallationResult_to_outcome( + PrfleInstRslt + ), + ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq); _ -> - % No work item exists, foward the ProfileInstallationResult - {} = es9p_client:request_json(Es9Req, BaseUrl) - end; + % No related work item exists, so we cannot do anything useful with the notification + % contents. + ok + end, + % foward the ProfileInstallationResult + {} = es9p_client:request_json(Es9Req, BaseUrl); {otherSignedNotification, OtherSignNotif} -> Es9Req = {handleNotification, #{ @@ -318,11 +292,8 @@ ), case EuiccPackageSigned of error -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, badPsmo}]}], - EsipaReq - ), + Outcome = [{[{eimProcedureError, badOrder}]}], + ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq), {eimPackageError, undefinedError}; _ -> EimSignature = crypto_utils:sign_euiccPackageSigned( @@ -344,11 +315,8 @@ ), case EuiccPackageSigned of error -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, badEco}]}], - EsipaReq - ), + Outcome = [{[{eimProcedureError, badOrder}]}], + ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq), {eimPackageError, undefinedError}; _ -> EimSignature = crypto_utils:sign_euiccPackageSigned( @@ -368,11 +336,8 @@ ), case IpaEuiccDataRequest of error -> - ok = mnesia_db_work:finish( - Pid, - [{[{procedureError, badEdr}]}], - EsipaReq - ), + Outcome = [{[{eimProcedureError, badOrder}]}], + ok = mnesia_db_work:finish(Pid, Outcome, EsipaReq), {eimPackageError, undefinedError}; _ -> IpaEuiccDataRequest @@ -380,7 +345,7 @@ none -> {eimPackageError, noEimPackageAvailable}; _ -> - ok = mnesia_db_work:finish(Pid, [{[{procedureError, badOrder}]}], EsipaReq), + ok = mnesia_db_work:finish(Pid, [{[{eimProcedureError, badOrder}]}], EsipaReq), {eimPackageError, undefinedError} end, {getEimPackageResponse, EsipaResp}; @@ -423,7 +388,8 @@ {provideEimPackageResultResponse, {emptyResponse, #{}}}; %Unsupported request handle_asn1(Pid, Request) -> - mnesia_db_work:finish(Pid, [{[{procedureError, abortedOrder}]}], unsupported), + Outcome = [{[{eimProcedureError, abortedOrder}]}], + mnesia_db_work:finish(Pid, Outcome, unsupported), logger:info( "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p,~nPid=~p~n", [Request, Pid] diff --git a/src/esipa_asn1_handler_utils.erl b/src/esipa_asn1_handler_utils.erl index 373922f..ebff01b 100644 --- a/src/esipa_asn1_handler_utils.erl +++ b/src/esipa_asn1_handler_utils.erl @@ -77,10 +77,10 @@ EuiccPackageResultDataSigned ); _ -> - [{[{euiccPackageErrorCode, counterValueMismatch}]}] + [{[{eimProcedureError, badCounter}]}] end; _ -> - [{[{procedureError, euiccSignatureInvalid}]}] + [{[{eimProcedureError, badSignature}]}] end; {euiccPackageErrorSigned, EuiccPackageErrorSigned} -> case @@ -95,15 +95,17 @@ ), case CheckCounterValue(EuiccPackageErrorDataSigned) of ok -> - [{[{euiccPackageErrorCode, EuiccPackageErrorCode}]}]; + [{[{euiccPackageError, EuiccPackageErrorCode}]}]; _ -> - [{[{euiccPackageErrorCode, counterValueMismatch}]}] + [{[{eimProcedureError, badCounter}]}] end; _ -> - [{[{procedureError, euiccSignatureInvalid}]}] + [{[{eimProcedureError, badSignature}]}] end; {euiccPackageErrorUnsigned, _} -> - [{[{euiccPackageErrorCode, undefinedError}]}] + [{[{euiccPackageError, undefinedError}]}]; + _ -> + [{[{eimProcedureError, badEuiccResult}]}] end,
mnesia_db_work:finish(Pid, Outcome, Debuginfo). @@ -127,5 +129,5 @@ EimTransactionId = maps:get(eimTransactionId, EimPackageResultResponseError), {_, _, _} = mnesia_db_work:pickup(Pid, EimTransactionId), EimPackageResultErrorCode = maps:get(eimPackageResultErrorCode, EimPackageResultResponseError), - Outcome = [{[{eimPackageError, EimPackageResultErrorCode}]}], + Outcome = [{[{eimPackageResultError, EimPackageResultErrorCode}]}], mnesia_db_work:finish(Pid, Outcome, Debuginfo). diff --git a/src/esipa_asn1_http_handler.erl b/src/esipa_asn1_http_handler.erl index 3b03826..fdb5706 100644 --- a/src/esipa_asn1_http_handler.erl +++ b/src/esipa_asn1_http_handler.erl @@ -61,7 +61,7 @@ ok; _ -> mnesia_db_work:finish( - maps:get(pid, Req0), [{[{procedureError, abortedOrder}]}], Reason + maps:get(pid, Req0), [{[{eimProcedureError, abortedOrder}]}], Reason ), logger:info( "Handling of IPAd request (ASN.1) terminated unexpectedly, Reason=~p Pid=~p~n", diff --git a/src/esipa_json_handler.erl b/src/esipa_json_handler.erl index c5d8368..a0911b5 100644 --- a/src/esipa_json_handler.erl +++ b/src/esipa_json_handler.erl @@ -412,7 +412,7 @@ end; %Unsupported request handle_json(Pid, Request) -> - mnesia_db_work:finish(Pid, [{[{procedureError, abortedOrder}]}], unsupported), + mnesia_db_work:finish(Pid, [{[{eimProcedureError, abortedOrder}]}], unsupported), logger:info( "Handling of IPAd request failed, the request type is unsupported,~nRequest=~p,~nPid=~p~n", [Request, Pid] diff --git a/src/esipa_json_http_handler.erl b/src/esipa_json_http_handler.erl index 7d2de97..20fb61a 100644 --- a/src/esipa_json_http_handler.erl +++ b/src/esipa_json_http_handler.erl @@ -56,7 +56,7 @@ ok; _ -> mnesia_db_work:finish( - maps:get(pid, Req0), [{[{procedureError, abortedOrder}]}], Reason + maps:get(pid, Req0), [{[{eimProcedureError, abortedOrder}]}], Reason ), logger:info( "Handling of IPAd request (JSON) terminated unexpectedly, Reason=~p Pid=~p~n", diff --git a/src/esipa_rest_utils.erl b/src/esipa_rest_utils.erl index 419bc0a..b481d1c 100644 --- a/src/esipa_rest_utils.erl +++ b/src/esipa_rest_utils.erl @@ -377,12 +377,12 @@
case ListProfileInfoResult of {profileInfoListOk, ProfileInfoListOk} -> - ProfileInfoList = [ProfileInfo2Json(O) || O <- ProfileInfoListOk], - ListProfileInfoResultValue = - {[{finalResult, successResult}, {profileInfoList, ProfileInfoList}]}, - {[{listProfileInfoResult, ListProfileInfoResultValue}]}; + ListProfileInfoResultRest = [ProfileInfo2Json(O) || O <- ProfileInfoListOk], + {[{listProfileInfoResult, ListProfileInfoResultRest}]}; + {profileInfoListError, ProfileInfoListError} -> + {[{profileInfoListError, ProfileInfoListError}]}; _ -> - {[{listProfileInfoResult, {[{finalResult, errorResult}]}}]} + {[{eimProcedureError, badEuiccResult}]} end.
result_to_json_listEimResult(ListEimResult) -> @@ -395,22 +395,24 @@ end,
case ListEimResult of + % Same here, let's flatten this {eimIdList, EimIdList} -> - EimIdInfoList = [EimIdList2Json(O) || O <- EimIdList], - ListEimResultValue = {[{finalResult, successResult}, {eimIdList, EimIdInfoList}]}, - {[{listEimResult, ListEimResultValue}]}; + ListEimResultRest = [EimIdList2Json(O) || O <- EimIdList], + {[{listEimResult, ListEimResultRest}]}; + {listEimError, ListEimError} -> + {[{listEimError, ListEimError}]}; _ -> - {[{listEimResult, {[{finalResult, errorResult}]}}]} + {[{eimProcedureError, badEuiccResult}]} end.
result_to_json_addEimResult(AddEimResult) -> case AddEimResult of {associationToken, AssociationToken} -> - {[{addEimResult, {[{addEimResultCode, ok}, {associationToken, AssociationToken}]}}]}; + {[{addEimResult, {[{associationToken, AssociationToken}]}}]}; {addEimResultCode, AddEimResultCode} -> {[{addEimResult, {[{addEimResultCode, AddEimResultCode}]}}]}; _ -> - {[{addEimResult, {[{addEimResultCode, malformedResult}]}}]} + {[{eimProcedureError, badEuiccResult}]} end.
result_to_json_getRATResult(GetRATResult) -> @@ -437,7 +439,7 @@ % generate a JSON encodeable outcome (JSON REST API) from an EuiccPackageResultDataSigned euiccPackageResultDataSigned_to_outcome(EuiccPackageResultDataSigned) -> EuiccResult = maps:get(euiccResult, EuiccPackageResultDataSigned), - Error = {[{error, malformedResult}]}, + Error = {[{eimProcedureError, badEuiccResult}]}, EuiccResultData2Json = fun(EuiccResultData) -> case EuiccResultData of {enableResult, EnableResult} -> @@ -485,31 +487,50 @@ profileInstallationResultData, ProfileInstallationResult ), NotificationMetadata = maps:get(notificationMetadata, ProfileInstallationResultData), + Iccid = maps:get(iccid, NotificationMetadata, <<"">>), FinalResult = maps:get(finalResult, ProfileInstallationResultData), - case FinalResult of - {successResult, _} -> - Iccid = maps:get(iccid, NotificationMetadata), + {successResult, SuccessResult} -> + Aid = maps:get(aid, SuccessResult), + SimaResponse = maps:get(simaResponse, SuccessResult), [ {[ {profileInstallationResult, {[ - {finalResult, successResult}, - {iccid, utils:binary_to_hex(Iccid)} + {iccid, utils:binary_to_hex(Iccid)}, + {aid, utils:binary_to_hex(Aid)}, + {simaResponse, utils:binary_to_hex(SimaResponse)} + ]}} + ]} + ]; + {errorResult, ErrorResult} -> + BppCommandId = maps:get(bppCommandId, ErrorResult), + ErrorReason = maps:get(errorReason, ErrorResult), + SimaResponse = maps:get(simaResponse, ErrorResult, <<"">>), + [ + {[ + {profileInstallationError, + {[ + {bppCommandId, BppCommandId}, + {errorReason, ErrorReason}, + {simaResponse, utils:binary_to_hex(SimaResponse)} ]}} ]} ]; _ -> - [{[{profileInstallationResult, {[{finalResult, errorResult}]}}]}] + {[{eimProcedureError, badEuiccResult}]} end.
% generate a JSON encodeable outcome (JSON REST API) from an CancelSessionResponse cancelSessionResponse_to_outcome(CancelSessionResponse) -> case CancelSessionResponse of - {cancelSessionResponseOk, _} -> - [{[{cancelSessionResult, ok}]}]; + {cancelSessionResponseOk, #{euiccCancelSessionSigned := EuiccCancelSessionSigned}} -> + CancelSessionReason = maps:get(reason, EuiccCancelSessionSigned), + [{[{cancelSessionReason, CancelSessionReason}]}]; + {cancelSessionResponseError, CancelSessionResponseError} -> + [{[{cancelSessionResponseError, CancelSessionResponseError}]}]; _ -> - [{[{cancelSessionResult, undefinedError}]}] + {[{eimProcedureError, badEuiccResult}]} end.
% Generate an ipaEuiccDataRequest from a eDR Order (JSON REST API) @@ -579,9 +600,9 @@ ], IpaEuiccDataJsonFiltered = {lists:filter(fun(Member) -> Member /= nil end, IpaEuiccDataJson)}, - [{[{euiccDataResult, {[{edrResult, ok}, {euiccData, IpaEuiccDataJsonFiltered}]}}]}]; + [{[{euiccDataResult, IpaEuiccDataJsonFiltered}]}]; {ipaEuiccDataResponseError, #{ipaEuiccDataErrorCode := IpaEuiccDataErrorCode}} -> - [{[{euiccDataResult, {[{edrResult, IpaEuiccDataErrorCode}]}}]}]; + [{[{ipaEuiccDataError, IpaEuiccDataErrorCode}]}]; _ -> - [{[{euiccDataResult, {[{edrResult, undefinedError}]}}]}] + [{[{eimProcedureError, badEuiccResult}]}] end. diff --git a/src/mnesia_db.erl b/src/mnesia_db.erl index 63028c4..62cd861 100644 --- a/src/mnesia_db.erl +++ b/src/mnesia_db.erl @@ -99,7 +99,7 @@ mnesia_db_rest:trans_set_status( ResourceId, done, - [{[{procedureError, abortedOrder}]}], + [{[{eimProcedureError, abortedOrder}]}], none ) end, diff --git a/src/mnesia_db_euicc.erl b/src/mnesia_db_euicc.erl index 2c18990..6940ebb 100644 --- a/src/mnesia_db_euicc.erl +++ b/src/mnesia_db_euicc.erl @@ -115,11 +115,14 @@ stateChangeCauseList -> mnesia:write(Row#euicc{stateChangeCauseList = Value}); _ -> + % eimProcedureError throw(badState) end; [] -> - throw(eidUnknown); + % eimProcedureError + throw(badEid); _ -> + % eimProcedureError throw(undefinedError) end.
@@ -142,11 +145,14 @@ stateChangeCauseList -> Row#euicc.stateChangeCauseList; _ -> + % eimProcedureError throw(badState) end; [] -> - throw(eidUnknown); + % eimProcedureError + throw(badEid); _ -> + % eimProcedureError throw(undefinedError) end.
@@ -244,6 +250,7 @@ ok = trans_state_set(EidValue, binary_to_atom(Name), Value), {[{Name, Value}]}; _ -> + % eimProcedureError throw(badOrder) end end, @@ -258,6 +265,7 @@ {[{<<"euicc">>, {[{<<"get">>, States}]}}]} -> [{[{euiccStateResult, [HandleStateGet(EidValue, State) || State <- States]}]}]; _ -> + % eimProcedureError throw(badOrder) end end, @@ -268,10 +276,10 @@ Outcome; {aborted, {throw, ErrorCode}} -> logger:error("eUICC: order process failed with error code ~p~n", [ErrorCode]), - [{[{procedureError, ErrorCode}]}]; + [{[{eimProcedureError, ErrorCode}]}]; _ -> logger:error("eUICC: order process failed, database error~n"), - [{[{procedureError, undefinedError}]}] + [{[{eimProcedureError, undefinedError}]}] end.
timer_rest_finish(RestResource, Outcome) -> diff --git a/src/mnesia_db_rest.erl b/src/mnesia_db_rest.erl index 0976beb..cef68c9 100644 --- a/src/mnesia_db_rest.erl +++ b/src/mnesia_db_rest.erl @@ -169,7 +169,7 @@ end,
% set status in the rest table - trans_set_status(ResourceId, done, [{[{procedureError, stuckOrder}]}], none) + trans_set_status(ResourceId, done, [{[{eimProcedureError, stuckOrder}]}], none) end,
% Find all rest resources that stall in status "work" and older than the specified timeout value @@ -202,7 +202,7 @@
% Remove Resource from work table and set an appropriate status in the rest table HandleResource = fun(ResourceId) -> - trans_set_status(ResourceId, done, [{[{procedureError, noshowOrder}]}], none) + trans_set_status(ResourceId, done, [{[{eimProcedureError, noshowOrder}]}], none) end,
% Find all rest resources that stall in status "work" and older than the specified timeout value diff --git a/src/mnesia_db_work.erl b/src/mnesia_db_work.erl index 1d488be..3c11112 100644 --- a/src/mnesia_db_work.erl +++ b/src/mnesia_db_work.erl @@ -35,7 +35,7 @@ {atomic, PidExists} = mnesia:transaction(TransPidExists), case PidExists of true -> - finish(Pid, [{[{procedureError, stuckOrder}]}], none); + finish(Pid, [{[{eimProcedureError, stuckOrder}]}], none); false -> ok end,