Schedule icon
KooCLI icon
If icon
SlackIncomingWebhook icon
Log icon

Huawei IAM Access Key Rotation Hygiene Sentinel

Audit Huawei Cloud IAM access keys for rotation age and alert Slack with the exact key ID before it becomes a security finding.

Categories
Infrastructure

A Huawei Cloud IAM permanent access key that is never rotated - issued once for a service integration and then forgotten - sits as a growing liability with no proactive warning from IAM itself. This blueprint lists a user's permanent access keys on a schedule and alerts Slack with the exact access key ID and age in days for anything active and past a configured rotation window.

How it works

  1. periodic_key_rotation_check (io.kestra.plugin.core.trigger.Schedule) runs once a day, explicitly passing huawei_region, target_user_id, and max_key_age_days through its own inputs: block so the flow is self-contained when the trigger fires. Shipped disabled so a manual run can be verified first.
  2. probe_list_access_keys (io.kestra.plugin.huawei.koocli.KooCLI) runs hcloud IAM ListPermanentAccessKeys, capturing the full credentials array - access key ID, status, and creation time for every permanent key the target user has.
  3. evaluate_key_rotation_hygiene (io.kestra.plugin.core.flow.If) branches on whether any active key's create_time is older than max_key_age_days.
    • then (STALE_ACCESS_KEY_DETECTED): alert_stale_access_keys reports every flagged key's access key ID and age to Slack.
    • else (HEALTHY): log_access_keys_healthy records the clean pass along with the total key count.
  4. log_audit_complete always runs last, printing the total key count regardless of which branch fired.
  5. The errors block alerts Slack separately if the flow itself fails outright - an invalid user ID, insufficient permissions, or invalid credentials.

What you get

  • A credential-hygiene answer built on IAM's own status and create_time fields, not a manually maintained spreadsheet of which service owns which access key and when it was last rotated.
  • The exact access key ID and age in the Slack alert itself, so rotation can be scoped to the specific credential instead of triggering a blanket "rotate everything" response.
  • A worked example of io.kestra.plugin.huawei.koocli.KooCLI - Huawei's direct equivalent of this repository's AwsCLI-based sentinels - targeting an IAM governance use case with no prior blueprint coverage of this plugin at all.

Who it's for

  • Security and platform teams running workloads on Huawei Cloud who need a recurring, automated check on permanent access key age, the kind of finding that otherwise only surfaces during a periodic manual audit or a compliance review.
  • Teams who issued a permanent access key for a specific integration and have no ongoing visibility into whether it has ever been rotated since.
  • Anyone evaluating the Huawei plugin who wants a worked example of KooCLI used for a read-only governance check, mirroring this repository's existing AwsCLI-based sentinel pattern on a different cloud provider.

Why orchestrate this with Kestra

Huawei Cloud IAM has no built-in "alert me when a permanent access key gets old" primitive - the key simply keeps working until someone manually checks or disables it. Kestra supplies the schedule, the HEALTHY/STALE_ACCESS_KEY_DETECTED classification as a first-class branch, and an execution history showing exactly when a key first crossed the rotation threshold.

Prerequisites

  • A Huawei Cloud account with at least one IAM user holding a permanent access key (update huawei_region, target_user_id). Account signup may require a payment method depending on region and promotional eligibility; Huawei's own free-package trials were not independently confirmed to be available without one in every case.
  • Huawei Cloud credentials with permission to call ListPermanentAccessKeys - entirely read-only, cannot create, disable, or delete any access key. Querying another IAM user's keys (rather than your own) requires administrator permissions.
  • A Slack incoming webhook for alerts.

Local testing: no open-source local emulator for Huawei Cloud IAM was identified. A real Huawei Cloud account is the only way to exercise this blueprint end to end.

Secrets

  • HUAWEI_ACCESS_KEY_ID / HUAWEI_SECRET_ACCESS_KEY: credentials for io.kestra.plugin.huawei.koocli.KooCLI.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used by alert_stale_access_keys and the errors block.
  • In Kestra OSS (no Enterprise secrets backend), secrets are supplied as environment variables prefixed SECRET_, base64-encoded - for example SECRET_HUAWEI_SECRET_ACCESS_KEY=$(echo -n '<your-secret-key>' | base64) - and read back in flows with {{ secret('NAME') }}.

Inputs

Input Type Default Description
huawei_region STRING eu-west-101 Region used to configure KooCLI profile
target_user_id STRING REPLACE-WITH-YOUR-IAM-USER-ID The IAM user ID whose permanent access keys are audited
max_key_age_days INT 90 Inactivity age threshold in days for active access keys

Outputs

  • outputs.probe_list_access_keys.vars.credentials (list): every permanent access key's user_id, access, status, create_time, and description (verified fields from ListPermanentAccessKeys's own documented response schema).

Quick start

  1. Identify a real Huawei Cloud IAM user ID with at least one permanent access key.
  2. Add the HUAWEI_ACCESS_KEY_ID, HUAWEI_SECRET_ACCESS_KEY, and SLACK_WEBHOOK_URL secrets.
  3. Run the flow manually and confirm log_access_keys_healthy fires if no key is overdue.
  4. Temporarily lower max_key_age_days below the real age of a known active key, and re-run to confirm alert_stale_access_keys fires with the correct access key ID and age.
  5. Enable periodic_key_rotation_check once you trust the check against your real account.

How to extend

  • Loop over several target_user_id values with io.kestra.plugin.core.flow.Loop to audit every service-account-style IAM user in an account in one run.
  • Add a remediation branch using a further KooCLI call to hcloud IAM DisablePermanentAccessKey on a flagged key, behind an explicit approval gate - deliberately kept out of this sentinel so the monitoring path never disables a credential on its own, which could break a live integration without warning.
  • Cross-reference inactive-status keys that are still present (not yet deleted) as a separate, lower-urgency cleanup signal alongside the rotation check this blueprint already performs.

Pitfalls

  • Huawei's create_time includes microsecond precision (YYYY-MM-DDTHH:mm:ss.ssssssZ, verified from Huawei's own API reference) - whether the jq fromdateiso8601 builtin bundled with this Kestra instance correctly parses the fractional-second suffix was not independently confirmed; some jq versions only accept whole-second ISO 8601 timestamps. Verify this specific parsing behavior in your own environment before relying on the computed age.
  • Querying another IAM user's keys requires administrator permissions - verified from Huawei's own API reference, which distinguishes self-service queries (no user_id needed) from administrator queries (user_id required). Running this with credentials that lack that permission surfaces as a failure through the errors block, not a false HEALTHY.
  • This sentinel does not see temporary/STS credentials - only permanent access keys returned by ListPermanentAccessKeys; short-lived credentials obtained via GetTemporaryCredentials expire on their own and are out of scope here.
  • This blueprint is UNTESTED against a live Huawei Cloud account. The CLI service/operation naming, the credentials/status/create_time/access output fields, and the user_id query parameter are taken verbatim from Huawei's own API reference and this plugin's own documented example pattern - but no Kestra engine was run to execute this flow end to end.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.