User Management- reporting

Product/components used and version/fix level:

Hi All,

I am part of IOT team and we use cumulocity IOT platform for our devices.
I need help with user management.

Detailed explanation of the problem:

we have 1000+ users added on to C8Y platform and have to check which user has not logged- in past 3 months, so that we can revoke their access.

I know that we can do it manually by checking in Audit logs - user login but as we have 1000+ users in 1 tenant and we have 50+ separate tenants operational so manual checking is not possible.

Is there any way we can automate this via APIs ?

Need suggestion form community.

Error messages / full error message screenshot / log file:

Question related to a free trial, or to a production (customer) instance?


the quick answer is that it can be done; I’d use a script to do what you ask. You could probably build a microservice but that’s out of the range of my technical skills since I’m an admin and not a developer.

Personally I’d search for login events in the audit log in the time frame desired. That has the user name in the event. Then I’d compare those users that have logged in against the list of authorized users.

I really hope that you have the list of accessing users stored in Active Directory or other means; I wouldn’t want to even try to manage 1000 local users. But if you do that, since you’re scripting anyway, it would be a straightforward item to notify either yourself or whoever manages AD group memberships to remove those users. Although I haven’t personally done it, I’m willing to bet that an API can deactivate local users. If you want to see that, open the console and access the developer screen (f12 on a Windows computer). Select the Network tab… Do the action you want to do and you can see they calls/results. Then you can see exactly what API call has been made and repeat that.

I’d also suggest having an API user in your Active Directory who has read-only access to those tenants. Then use a JWT token to access those tenancies for reporting. It’s not ideal but you don’t want to use your accounts to run an automated process.

1 Like

You can use the below two options to build your script, that internally uses the Cumulocity standard REST APIs. The Below two APIs could be required (User API and Audit APIs)

Using goc8ycli -
Using Python SDK - GitHub - SoftwareAG/cumulocity-python-api: Python client for the Cumulocity REST API. Created by Global Competency Center IoT


1 Like


few important points you should be aware of:

  • There are no login events in Audit record in case your tenant is configured to use Basic Authentication. For OAI and logins via SSO there are such audit entries.
  • Make sure to NOT delete or disable any device-users (starting with device_), depending on your device integration, this could get very troublesome to put them back in bootstrapping mode
  • Retention period for AUDIT or “*” might be less than your 3 months - this should be checked before deriving any user inactivity based on Audit Logs

Here are some steps I would see for automation:

  1. Prerequisite 1: Check if basic authentication is activated as default in your tenant.
    API endpoint: GET If the entry with type=“BASIC” has visibleOnLoginPage=true, abort.

  2. Prerequisite 2: Check Retention for Audit Records.
    API endpoint: GET If retention < 3 months, abort. Make sure to not only check the one with dataType=AUDIT but also dataType=*.

  3. Prerequisite 3: Check if tenant auth config was changed in past 3 month.
    API endpoint: GET{timeStamp now - 12 weeks}&type=TenantAuthConfig&withTotalElements=true. If statistics.totalElements > 0, abort.

  4. Collect all login events of past 3 months, group/unique the Usernames in list A.
    API endpoint: GET{timeStamp now - 12 weeks}&pageSize=2000&type=UserAuthentication. The result will be paged, make sure to iterate via the next-links.

  5. Collect ids of all active users in your tenant in list B.
    API endpoint GET The result will be paged, make sure to iterate via the next-links.

  6. Find the Users that are Part of List B, but not in list A and disable them
    API endpoint:

PUT /user/{tenantid}/users/{userid} HTTP/1.1
Accept: application/json
Authorization: Bearer eyJ...
Content-Type: application/json

  1. Optional: Create an Audit Log entry to historize that this script was running and which users it disabled.
    API endpoint:
POST /audit/auditRecords HTTP/1.1
Accept: application/json
Authorization: Bearer ey...
Content-Type: application/json

{"activity":"Disabled Users due to inactivity","disabledUsers":["john.doe","jane.smith"],"source":{"id":"1"},"text":"Script executed to disable Users with no login in past 3 months","time":"2024-03-30T08:00:00.000+01:00","type":"manualScriptRun"}

Deleting Users can be sensitive…you might want to first disable them (step 6) and only delete them after some grace period. If you want to do a delete instead, you can use DELETE /user/t2004070892/users/{userid}

Details about the API endpoints you can find here: Cumulocity IoT - OpenAPI Specification.

// If helpful, I could draft a go-c8y-cli script with above steps tomorrow.


Another option would be to set the password validity and use that to gauge if a user is active or not.

For example:

  1. Set the password validity say to 60 days (in the Administration > Settings > Authentication > Password Validity Limit)
  2. Periodically run a script to delete the users by checking the lastPasswordChange date in the user object. Ideally you should give users a grace period to allow active users to renew their passwords after they have expired, e.g. 90 days

Here is a small bash script which uses go-c8y-cli which does step 2 (see comments inside script for details)

#!/usr/bin/env bash

# Set CI to true to disable all prompts

# The following one-liner does:
# 1. List all users where the last password change is older than 90 days (Note: this is a client side filter, so don't run if you have > 10K users)
# 2. Create an audit entry (technically you don't need this, but it would give you better tracking which users are deleted by your automation)
# 3. Delete the user

c8y users list --filter "lastPasswordChange olderthan -90d" --includeAll \
| c8y auditrecords create \
    --activity "Disabled Users due to inactivity" \
    --text "Script executed to disable Users with no login in past 3 months" \
    --type "manualScriptRun" \
    --template "{user:}" \
    --select user --output csv \
| c8y users delete

The obvious downside for users is that they maybe forced to change their password more frequently then they expect, however the upside is that they will be forced into good security practices.


There is a slightly different variant that if you don’t want to delete the user, but instead just disable the account, then you can use c8y users update instead of c8y users delete (but everything else stays the same).

c8y users update --enabled=false

Though technically speaking, if you enforce a password validity limit, then maybe you don’t need to do disable the users at all (unless if you want to enforce a manual process if the user wants to reactivate their account).