Skip to content

refactor: replace from awsiot-credentialhelper[security]#135

Merged
airkei merged 5 commits intomainfrom
feat/replace-from-awsiot-credentialhelper
Feb 13, 2026
Merged

refactor: replace from awsiot-credentialhelper[security]#135
airkei merged 5 commits intomainfrom
feat/replace-from-awsiot-credentialhelper

Conversation

@airkei
Copy link
Contributor

@airkei airkei commented Feb 12, 2026

Why

https://tier4.atlassian.net/browse/T4DEV-45348
https://tier4.atlassian.net/browse/T4DEV-45347
https://tier4.atlassian.net/browse/T4DEV-45345

  1. awsiot_credentialhelper depends on a legacy version of urllib3 that contains known vulnerabilities.
  2. awsiot_credentialhelper repository was archived without addressing this issue
    https://github.com/awslabs/aws-iot-core-credential-provider-session-helper

What

Implement functionality equivalent to awsiot_credentialhelper based on https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html

  • remove awsiot_credentialhelper dependency
  • use awscrt for HTTPS communication for both file and TPM(PKCS#11).
  • secret token is stored only in memory.

Tests

On the VM, verified that the otaclient logs were successfully sent to CloudWatch in both the file-based and TPM (PKCS#11) cases.

@airkei airkei self-assigned this Feb 12, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/otaclient_iot_logging_server
   __init__.py30100% 
   __main__.py19194%52
   _common.py190100% 
   _log_setting.py261061%63, 65–66, 68–69, 73–74, 77–78, 80
   _sd_notify.py32875%41, 51, 56–58, 64–66
   _utils.py50296%73, 137
   _version.py130100% 
   aws_iot_logger.py844052%70–72, 74–75, 78, 81–82, 85, 89–92, 96–98, 101–103, 106–111, 126, 132–134, 136–140, 144, 191, 198–201
   boto3_session.py913561%66, 74–75, 77, 92–93, 97, 99, 107, 148, 160, 190–191, 193–195, 197–199, 201, 208–210, 212–213, 215, 219, 221–222, 224–226, 228, 257–258
   config_file_monitor.py43686%63–65, 82–84
   configs.py45197%73
   ecu_info.py36197%74
   greengrass_config.py100595%154, 272–275
   log_proxy_server.py482939%46–47, 49–51, 54–56, 59–60, 64, 67, 69–70, 73, 76, 80–82, 84–85, 89–90, 97–98, 100–101, 106, 112
   servicer.py58591%59, 101–103, 119
src/otaclient_iot_logging_server/v1
   _types.py420100% 
   api_stub.py140100% 
TOTAL72314380% 

Tests Skipped Failures Errors Time
61 0 💤 0 ❌ 0 🔥 19.314s ⏱️

@airkei airkei changed the title refactor: replace from awsiot-credentialhelper refactor: replace from awsiot-credentialhelper[security] Feb 12, 2026
# ------ credential fetching ------ #
#
# AWS IoT Core Credential Provider API:
# https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sequence follows the official spec.
Making an HTTPS request to the credentials provider to get a security token.

Comment on lines +143 to +168
def _build_tls_context_from_path(
cert_path: str,
key_path: str,
) -> TlsContextOptions:
"""Build TLS context options using plain certificate/key files."""
return TlsContextOptions.create_client_with_mtls_from_path(
cert_filepath=cert_path,
pk_filepath=key_path,
)


def _build_tls_context_pkcs11(
cert_pem: bytes,
pkcs11_cfg: PKCS11Config,
private_key_label: Optional[str] = None,
) -> TlsContextOptions:
"""Build TLS context options using PKCS#11 for private key operations."""
return TlsContextOptions.create_client_with_mtls_pkcs11(
pkcs11_lib=Pkcs11Lib(file=pkcs11_cfg.pkcs11_lib),
user_pin=pkcs11_cfg.user_pin,
slot_id=int(pkcs11_cfg.slot_id),
token_label=None, # type: ignore[arg-type]
private_key_label=private_key_label, # type: ignore[arg-type]
cert_file_path=None, # type: ignore[arg-type]
cert_file_contents=cert_pem,
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The differences between File and PKCS#11 are limited to two functions. suggest simply separating the functions rather than introducing an abstract base class.

credential_url: str,
) -> Dict[str, Any]:
"""Parse credential provider response, raising on non-200 status."""
if response_status != HTTPStatus.OK:
Copy link
Contributor Author

@airkei airkei Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition(only 200) follows the original implementation in awsiot-credentialhelper.

Comment on lines +158 to +161
"access_key": "AKIAIOSFODNN7EXAMPLE",
"secret_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"token": "FwoGZXIvYXdzEBY...",
"expiry_time": "2099-01-01T00:00:00Z",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test keys are used in official document as references, no security risk.
https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html

]
dependencies = [
"aiohttp>=3.10.11,<3.14",
"awsiot-credentialhelper>=0.6,<1.1",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed.

dependencies = [
"aiohttp>=3.10.11,<3.14",
"awsiot-credentialhelper>=0.6,<1.1",
"awscrt>=0.16.9,<0.32",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

direct dependency.

# botocore
urllib3==1.26.20 ; python_full_version < '3.10'
# via botocore
urllib3==2.6.3 ; python_full_version >= '3.10'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this version resolves the vulnerability.

@airkei airkei force-pushed the feat/replace-from-awsiot-credentialhelper branch from 9c092cc to 084547d Compare February 12, 2026 09:19
@sonarqubecloud
Copy link

@airkei airkei marked this pull request as ready for review February 12, 2026 09:21
@airkei airkei requested a review from a team as a code owner February 12, 2026 09:21
Copy link

@timothylin timothylin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@Bodong-Yang Bodong-Yang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, LGTM!

@airkei airkei merged commit 56e2931 into main Feb 13, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants