Cloud Object Storage
Object storage on Converge Cloud is an HTTP API of its own. It does not share a hostname, a request shape or a signing algorithm with the rest of the platform, so a client written for the other services will not reach it.
- The domain is
convergecloudcos.com, notconvergecloud.com. - Requests are REST — a path, a query string and an XML body. There is no action header and no JSON envelope.
- The HTTP status code carries the result. The other services answer
200even for failures; object storage returns404,403and400with their standard HTTP meanings.
Endpoints
There are two host forms. The correct host depends on whether the request targets the account or a single bucket.
| Purpose | Host |
|---|---|
| Listing the buckets of the account | cos.luzon.convergecloudcos.com |
| Everything about a bucket or an object | <bucket>-<appid>.cos.luzon.convergecloudcos.com |
Prefixing the list-buckets host with service. — the form some clients default to — is rejected on Converge Cloud with 400 InvalidRequest, asking for a bucket in <bucketname>-<appid> form. Address cos.luzon.convergecloudcos.com directly.
Addressing a bucket
A bucket is addressed by hostname, and that hostname carries two things: the bucket name and the account AppId, joined by a hyphen. The AppId is not optional and it is not part of the path — a bucket called reports on AppId 1250000000 is reached at reports-1250000000.cos.luzon.convergecloudcos.com.
The AppId is a different number from the account UIN, and there is no call that returns it by name. Read it from cam:QueryApiKey, which returns the AppId in the SecretProjectId field. The account UIN is the Owner.ID of a bucket listing, and QueryApiKey takes the UIN as TargetUin.
A bucket that does not exist under the caller's AppId answers 404 NoSuchBucket. The same name under another account's AppId answers 403 AccessDenied, which is also the result of a mistyped AppId. When a request to an existing bucket returns 403, Converge Cloud recommends verifying the AppId in the hostname before reviewing access policies.
Signing a request
Object storage uses its own signature. The scheme the other Converge Cloud services use does not apply here, and neither signer can produce the other's header.
Authorization: q-sign-algorithm=sha1
&q-ak=<SecretId>
&q-sign-time=<start>;<end>
&q-key-time=<start>;<end>
&q-header-list=<signed headers, sorted>
&q-url-param-list=<signed query parameters, sorted>
&q-signature=<hex>q-sign-time and q-key-time are a pair of Unix seconds written start;end, and they bound how long the signature is valid. q-header-list and q-url-param-list name which headers and query parameters the signature covers, lowercased and sorted. The signature itself is derived in four steps:
SignKey = HMAC-SHA1(SecretKey, KeyTime)
HttpString = method + "\n" + path + "\n" + params + "\n" + headers + "\n"
StringToSign = "sha1" + "\n" + SignTime + "\n" + SHA1(HttpString) + "\n"
Signature = HMAC-SHA1(SignKey, StringToSign)params and headers are the signed query parameters and headers, URL-encoded, lowercased, sorted by key and joined with &. At minimum the host header is signed. Temporary credentials add the session token in an x-cos-security-token header.
Operations
Operations are grouped by scope: account, bucket and object.
Account operations
Bucket operations
Object operations
Errors
Failures come back as an XML Error document with a real HTTP status code. Code is the field to branch on; RequestId is what to quote when asking for help.
<?xml version='1.0' encoding='utf-8' ?>
<Error>
<Code>NoSuchBucket</Code>
<Message>The specified bucket does not exist.</Message>
<Resource>example-bucket-1250000000.cos.luzon.convergecloudcos.com</Resource>
<RequestId>NmFhYmNiZjJfZDAxMjMyMGFfNmMxZTlfNjZhNWU4</RequestId>
</Error>| Code | HTTP | What it means |
|---|---|---|
| NoSuchBucket | 404 | The AppId in the hostname is yours, but no bucket of that name exists. |
| AccessDenied | 403 | The bucket belongs to a different AppId, or the credential may not touch it. A mistyped AppId produces this rather than NoSuchBucket. |
| InvalidRequest | 400 | The request reached a host that expects the AppId form. See the note on the list-buckets host. |
| NoSuchCORSConfiguration | 404 | No cross-origin rules are set on the bucket. |
| NoSuchLifecycleConfiguration | 404 | No lifecycle rules are set on the bucket. |
Notes for client authors
The object storage endpoint presents a valid public certificate, but sends an older cross-signed root along with it. Python's bundled trust store reads that as self-signed certificate in certificate chain and refuses the connection, while browsers and curl verify it without complaint. Converge Cloud recommends supplying a current CA bundle in this case, rather than disabling verification.
Buckets start with no cross-origin rules — a CORS read answers 404 until CORS rules are configured. Until then, only server-side callers can reach the bucket.
luzon is the region for object storage, the same one the rest of the platform uses. It appears in the hostname and is returned by the bucket location call.
