Object storage

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.

Three things differ from every other service
  • The domain is convergecloudcos.com, not convergecloud.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 200 even for failures; object storage returns 404, 403 and 400 with 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.

PurposeHost
Listing the buckets of the accountcos.luzon.convergecloudcos.com
Everything about a bucket or an object<bucket>-<appid>.cos.luzon.convergecloudcos.com
Use the bare host to list buckets

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.

Finding the AppId

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 wrong AppId looks like a permission problem

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 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:

Derivation
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.

Error shape
<?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>
CodeHTTPWhat it means
NoSuchBucket404The AppId in the hostname is yours, but no bucket of that name exists.
AccessDenied403The bucket belongs to a different AppId, or the credential may not touch it. A mistyped AppId produces this rather than NoSuchBucket.
InvalidRequest400The request reached a host that expects the AppId form. See the note on the list-buckets host.
NoSuchCORSConfiguration404No cross-origin rules are set on the bucket.
NoSuchLifecycleConfiguration404No lifecycle rules are set on the bucket.

Notes for client authors

Python rejects the certificate; the certificate is fine

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.

A new bucket is not reachable from a browser

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.

Region

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.