When running app-store-connect actions with private key that is not issued by App Store Connect (i.e. a valid PEM encoded private key that is not elliptic curve private key) then generating JSON web token for API requests fails and consequently the whole action fails unexpectedly:
$ APP_STORE_CONNECT_PRIVATE_KEY=@file:/tmp/invalid-key.pk app-store-connect apps get 1496105355
Get App 1496105355
Executing "app-store-connect apps get" failed unexpectedly. Detailed logs are available at "/var/folders/wr/c44p23x10f302_kfbj32z0p80000gn/T/codemagic-13-12-23.log". To see more details about the error, add "--verbose" command line option.
Output with --verbose option
```python
$APP_STORE_CONNECT_PRIVATE_KEY=@file:/tmp/invalid-key.pk app-store-connect apps get 1496105355 --verbose
[14:15:23] INFO > Get App 1496105355
[14:15:23] DEBUG > Load JWT for App Store Connect key 'KXCJ7SZ6L7' from disk cache
[14:15:23] WARNING > Executing "app-store-connect apps get" failed unexpectedly. Detailed logs are available at "/var/folders/wr/c44p23x10f302_kfbj32z0p80000gn/T/codemagic-13-12-23.log".
[14:15:23] ERROR > Exception traceback:
Traceback (most recent call last):
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 243, in invoke_cli
CliApp._running_app._invoke_action(args)
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 184, in _invoke_action
return cli_action(**action_args)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 496, in wrapper
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/tools/_app_store_connect/action_groups/apps_action_group.py", line 39, in get_app
return self._get_resource(application_id, self.api_client.apps, should_print)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/tools/_app_store_connect/resource_manager_mixin.py", line 62, in _get_resource
resource = read_resource(resource_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/apps/apps.py", line 67, in read
response = self.client.session.get(f"{self.client.API_URL}/apps/{app_id}").json()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/requests/sessions.py", line 602, in get
return self.request("GET", url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_session.py", line 97, in request
return self._do_request(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_session.py", line 68, in _do_request
headers.update(self._auth_headers_factory())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_client.py", line 76, in generate_auth_headers
return {"Authorization": f"Bearer {self.jwt}"}
^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_client.py", line 72, in jwt
jwt = self._jwt_manager.get_jwt()
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 148, in get_jwt
self._jwt = self._load_jwt_from_disk()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 110, in _load_jwt_from_disk
payload = self._decode_payload(token)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 93, in _decode_payload
return jwt.decode(
^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jwt.py", line 210, in decode
decoded = self.decode_complete(
^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jwt.py", line 151, in decode_complete
decoded = api_jws.decode_complete(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jws.py", line 209, in decode_complete
self._verify_signature(signing_input, header, signature, key, algorithms)
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jws.py", line 307, in _verify_signature
prepared_key = alg_obj.prepare_key(key)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/algorithms.py", line 525, in prepare_key
raise InvalidKeyError(
jwt.exceptions.InvalidKeyError: Expecting a EllipticCurvePrivateKey/EllipticCurvePublicKey. Wrong key provided for ECDSA algorithms
```
None of it is particularly useful for the users. To avoid that from happening, validate that the provided key can be used for JWT generation beforehand when action is invoked from command line (not via Python API), and issue a proper actionable error message:
$ APP_STORE_CONNECT_PRIVATE_KEY=@file:/tmp/invalid-key.pk app-store-connect apps get 1496105355
usage: app-store-connect [-h] [--log-stream {stderr,stdout}] [--no-color] [--version] [-s] [-v]
{app-store-version-localizations,app-store-version-submissions,app-store-versions,apps,beta-app-review-submissions,beta-build-localizations,beta-groups,builds,create-bundle-id,create-certificate,create-profile,delete-bundle-id,delete-certificate,delete-profile,fetch-signing-files,get-bundle-id,get-certificate,get-latest-app-store-build-number,get-latest-build-number,get-latest-testflight-build-number,get-profile,list-builds,list-bundle-id-profiles,list-bundle-ids,list-certificates,list-devices,list-profiles,publish,register-device,review-submission-items,review-submissions}
...
app-store-connect: error: argument --private-key: Invalid App Store Connect API key. Make sure to use the private API key downloaded from App Store Connect. Read more about creating App Store Connect API keys from https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api
When running
app-store-connect
actions with private key that is not issued by App Store Connect (i.e. a valid PEM encoded private key that is not elliptic curve private key) then generating JSON web token for API requests fails and consequently the whole action fails unexpectedly:Output with
```python $APP_STORE_CONNECT_PRIVATE_KEY=@file:/tmp/invalid-key.pk app-store-connect apps get 1496105355 --verbose [14:15:23] INFO > Get App 1496105355 [14:15:23] DEBUG > Load JWT for App Store Connect key 'KXCJ7SZ6L7' from disk cache [14:15:23] WARNING > Executing "app-store-connect apps get" failed unexpectedly. Detailed logs are available at "/var/folders/wr/c44p23x10f302_kfbj32z0p80000gn/T/codemagic-13-12-23.log". [14:15:23] ERROR > Exception traceback: Traceback (most recent call last): File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 243, in invoke_cli CliApp._running_app._invoke_action(args) File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 184, in _invoke_action return cli_action(**action_args) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/cli/cli_app.py", line 496, in wrapper return func(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/tools/_app_store_connect/action_groups/apps_action_group.py", line 39, in get_app return self._get_resource(application_id, self.api_client.apps, should_print) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/tools/_app_store_connect/resource_manager_mixin.py", line 62, in _get_resource resource = read_resource(resource_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/apps/apps.py", line 67, in read response = self.client.session.get(f"{self.client.API_URL}/apps/{app_id}").json() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/requests/sessions.py", line 602, in get return self.request("GET", url, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_session.py", line 97, in request return self._do_request(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_session.py", line 68, in _do_request headers.update(self._auth_headers_factory()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_client.py", line 76, in generate_auth_headers return {"Authorization": f"Bearer {self.jwt}"} ^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/api_client.py", line 72, in jwt jwt = self._jwt_manager.get_jwt() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 148, in get_jwt self._jwt = self._load_jwt_from_disk() ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 110, in _load_jwt_from_disk payload = self._decode_payload(token) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/codemagic/apple/app_store_connect/json_web_token_manager.py", line 93, in _decode_payload return jwt.decode( ^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jwt.py", line 210, in decode decoded = self.decode_complete( ^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jwt.py", line 151, in decode_complete decoded = api_jws.decode_complete( ^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jws.py", line 209, in decode_complete self._verify_signature(signing_input, header, signature, key, algorithms) File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/api_jws.py", line 307, in _verify_signature prepared_key = alg_obj.prepare_key(key) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/priit/.pyenv/versions/3.12.0/lib/python3.12/site-packages/jwt/algorithms.py", line 525, in prepare_key raise InvalidKeyError( jwt.exceptions.InvalidKeyError: Expecting a EllipticCurvePrivateKey/EllipticCurvePublicKey. Wrong key provided for ECDSA algorithms ```--verbose
optionNone of it is particularly useful for the users. To avoid that from happening, validate that the provided key can be used for JWT generation beforehand when action is invoked from command line (not via Python API), and issue a proper actionable error message: