Access Key support was added to Cloud API in TRITON-2152#icft=TRITON-2152
The Cloud API Access Key endpoints are undocumented and need a few changes to support Manta S3 features. These changes should be made before other Triton services such as Manta depend upon the Access Keys.
Here’s an example CloudAPI response for a GET to /$account/accesskeys
{
"dn": "accesskeyid=ac8f5542e901da35de1c8d0d146a7ad0, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc",
"controls": [],
"accesskeyid": "ac8f5542e901da35de1c8d0d146a7ad0",
"accesskeysecret": "a1f7343ac37aab73d79efed54a27a62d9185bf05417515b3d891343a37942742",
"created": "2025-10-20T14:35:17.113Z",
"objectclass": "accesskey",
"status": "Active"
}
Proposed Changes:
Access Key response objects need an optional description field.
The POST /$account/accesskeys endpoint used to create an Access Key should return the accesskeysecret only at creation time and should be omitted for all other responses.
It should be possible to update the status of an Access Key to one of: Active, Inactive, or Expired to align with AWS. Only Active keys should be honored for authentication.
Access Key response objects should have an updated field.
AWS only allows 2 Access Keys on an account, CloudAPI should have some limit here even if its fairly high (32?)
controls , objectclass and dn properties should be omitted from CloudAPI responses, they are properties from UFDS/ldapjs.
node-triton should be updated to support creating, listing, and updating access keys.
Should confirm the endpoints honor policies and subusers (e.g. CAN createaccesskey).
The CloudAPI endpoints needs to be documented: TRITON-2511
Possible future changes considered out of scope for this issue:
Access keys could benefit from an expiration field. AWS doesn't support an expiration on access keys (an external process is required to expire a key) but, adding this field and supporting it in CloudAPI would be an improvement over the AWS implementation. The Manta S3 functionality needs to separately support temporary tokens and that feature would also cover this use case.
The AWS console shows the last time a key was used (though it is not exposed on the key metadata itself.) Having a lastused field stored on keys would help answer the common question: “Are we still using this key?”. Updating this for property every request is likely very expensive however and likely needs some more consideration.
The secret access key stored in UFDS should be encrypted, we are unable to hash them as the unhashed value is required for signature validation. This functionality isn't exposed by Cloud API so this change can occur later.
Using access keys for Cloud API authentication is out of scope for this issue (Manta S3 support for now.)
triton-go should be updated for any changes made to behavior here.
A user can manage keys for a subuser but subusers cannot manage their own keys through RBAC. accesskesy will first need to be setup as a valid resource type in CloudAPI.
POST /$acccount/accesskeys Request: (empty) or {}
Response:
{
"accesskeyid": "eb97791eb76601cc87361550bee06aa2",
"accesskeysecret": "e2a975cecc93a19041150ed3265f36dd1d54d23942d6a958b7c2bb354eaa8ebe",
"created": "2025-10-20T16:10:29.223Z",
"updated": "2025-10-20T16:10:29.223Z",
"description": null,
"status": "Active"
}
POST /$acccount/accesskeys Request:
{
"description": "This key is for the dev environment"
}
Response:
{
"accesskeyid": "eb97791eb76601cc87361550bee06aa2",
"accesskeysecret": "e2a975cecc93a19041150ed3265f36dd1d54d23942d6a958b7c2bb354eaa8ebe",
"created": "2025-10-20T16:10:29.223Z",
"updated": "2025-10-20T16:10:29.223Z",
"description": "This key is for the dev environment"
"status": "Active"
}
POST /$acccount/accesskeys/eb97791eb76601cc87361550bee06aa2 Request:
{
"status": "Inactive"
}
Response:
Note: accesskeysecret is not returned for this endpoint. It is only returned to the client on creation.
{
"accesskeyid": "eb97791eb76601cc87361550bee06aa2",
"created": "2025-10-20T16:10:29.223Z",
"updated": "2025-10-20T16:11:01.034Z",
"description": "This key is for the dev environment",
"status": "Inactive"
}
Travis Paul commented on 2025-10-20T14:18:45.055-0400 (edited 2025-10-20T14:29:49.352-0400):
We should also give some thought to the secret key format, currently it’s just hex but using a custom prefix (e.g. tdc-a1f7343ac37aab73d79efed54a27a62d9185bf05417515b3d891343a37942742) might have some benefits for detecting accidental exposure.
It could also be more compact by using base64 instead of hex output.
The key generation is implemented here: files#diff-92bbac9a308cd5fcf9db165841f2d90ce981baddcb2b1e26cfff170929af3bd1R3109
Which could easily be changed to something like:
'TDC_' + crypto.randomBytes(32).toString('base64') // TDC_Wx1YcMTYgLx88JLsDJk2iU6GjgWQk32d6rxZt+Vlues=
Travis Paul commented on 2025-10-28T16:28:11.473-0400:
AccessKeys created before v7.5.0 will be missing required properties, have an invalid accesskeysecret, and are unable to be used for authentication.
These AccessKeys weren't yet used anywhere within Triton but the undocumented CloudAPI endpoints existed and its possible that some installations may have
some of these older entries. node-ufds and cloud-api will return such keys as 'Inactive' but will need to be manually deleted from Moray as
UFDS's validation prevents updating or deleting these records:
delobject ufds_o_smartdc \
"accesskeyid=$ACCESSKEYID, uuid=$USER_UUID, ou=users, o=smartdc"
Carlos Neira commented on 2025-10-30T14:41:42.847-0400:
I just tested this change using the following images
[root@headnode (coal) ~]# sdcadm instances svc=cloudapi svc=ufds svc=mahi
INSTANCE SERVICE HOSTNAME VERSION ALIAS
be0dc4b6-8c96-4637-9f8c-f9d6c5b820fb cloudapi headnode PR-153-20251028T202511Z-g3d1ea86 cloudapi0
280f3714-72a9-4b19-ab7f-e805edd2732c mahi headnode MANTA-5471-20250701T024602Z-gca551e2 mahi0
cb7465dc-e173-45df-bc4e-4473fef322b3 ufds headnode PR-29-20251028T202434Z-g34e8c09 ufds0
Creation of access keys works as expected:
/tmp/ cloudapi /neirac/accesskeys -X POST | json -H
{
"accesskeyid": "7f39c931252939622bde5c5ea42856f2",
"status": "Active",
"created": "2025-10-30T18:22:49.256Z",
"updated": "2025-10-30T18:22:49.256Z",
"accesskeysecret": "tdc_-EnCUgVRxeH2B7OMD_SAfXl-097ix8VSMPKiX6oUE9s8Afw1"
}
Then I tested authentication using s3cmd with the set of keys
/tmp/ cat ~/.s3cfg.new
[default]
access_key = 7f39c931252939622bde5c5ea42856f2
secret_key = tdc_-EnCUgVRxeH2B7OMD_SAfXl-097ix8VSMPKiX6oUE9s8Afw1
host_base = localhost:8080
host_bucket = localhost:8080
use_https = True
region = us-east-1
signature_v2 = False
/tmp/ s3cmd --no-check-certificate -c ~/.s3cfg.new ls s3://dnd
2025-10-30 18:26 DIROBJ s3://dnd/.mpu-parts/
2025-10-28 12:19 5368709120 s3://dnd/5gtest6
2025-10-29 20:11 49 s3://dnd/autotest-690274d855.txt
2025-10-29 20:12 49 s3://dnd/autotest-690275424d.txt
2025-10-30 12:05 40 s3://dnd/test00
2025-10-28 12:23 5368709120 s3://dnd/thishashis334.5g
Then, to make sure everything in ok, I ran the S3 test suite and ALL test passed.
-e [2025-10-30 15:40:00] ====================================================================
-e [2025-10-30 15:40:00] AWS CLI Test Results Summary
-e [2025-10-30 15:40:00] ====================================================================
-e Tests Passed: 207
-e Tests Failed: 0