Documentation navigation
← Back to Jupiter Storage

Security Policies

Security Policies are enforced automatically at the gateway for every Storage request. Only the team API key, minted in the console, bypasses policies. Bucket operations can only be accessed with the team API key; therefore, they are not included in policies. For security, authorization is denied by default, meaning a user or group of users must be granted access to perform any operation on any resource; otherwise, it will be forbidden. The only exception is downloading objects from public buckets.

How actions, users, and resources are automatically mapped to policy data

You do not need to write any policy verification engine or custom gateway. For every request, we extract the relevant details and map them onto policy entities and actions. All Cedar policies have a Principal (who is it), Action (what are they doing), and Resource (what resource is their action targeting).

Principal

The principal is always the user making the request. If they are authenticated with Jupiter Auth and the request includes their access token in the Authorization header, it will be parsed and verified, and the claims will be mapped onto the principal entity. The standard default claims from the access token will be included under the principal object, while the custom configurable claims (user_attributes, system_attributes, custom_claims) will be passed dynamically to the context.

Standard claims included under the principal

ClaimType
subjectstring
audiencestring
issued_atLong
expires_atLong
issuerstring
emailstring
phonestring
rolestring
session_idstring
amrstring (aal1, aal2, aal3)
is_anonymousbool
permit (  principal,  action == JupiterStorage::Action::"GetObject",  resource)when {  principal.is_anonymous == false};

Optional dynamic claims under the context

ClaimType
user_attributesRecord
system_attributesRecord
custom_claimsRecord
permit (  principal,  action == JupiterStorage::Action::"GetObject",  resource)when {  context.user_attributes has age &&  context.user_attributes.age >= 18};

Action

Actions are the specific operations that the user tries to perform. For Storage requests, actions are mapped directly from the API request to Storage actions.

ActionCedar Action Name
GetObjectJupiterStorage::Action::"GetObject"
ListObjectsJupiterStorage::Action::"ListObjects"
DeleteObjectJupiterStorage::Action::"DeleteObject"
UploadObjectJupiterStorage::Action::"UploadObject"
DownloadObjectJupiterStorage::Action::"DownloadObject"
StartMultipartUploadJupiterStorage::Action::"StartMultipartUpload"
GetMultipartUploadJupiterStorage::Action::"GetMultipartUpload"
UploadMultipartPartJupiterStorage::Action::"UploadMultipartPart"
ListMultipartUploadPartsJupiterStorage::Action::"ListMultipartUploadParts"
GetMultipartUploadPartJupiterStorage::Action::"GetMultipartUploadPart"
CompleteMultipartUploadJupiterStorage::Action::"CompleteMultipartUpload"
AbortMultipartUploadJupiterStorage::Action::"AbortMultipartUpload"
DeleteObjectsJupiterStorage::Action::"DeleteObjects"
CopyObjectJupiterStorage::Action::"CopyObject"
UpdateObjectJupiterStorage::Action::"UpdateObjectMetadata"
ListMultipartUploadsJupiterStorage::Action::"ListMultipartUploads"
UploadPartCopyJupiterStorage::Action::"UploadPartCopy"

For example, if you have an app that allows users to upload content, such as photos, and users on the free tier can only access uploaded data without posting, you could use the following policy.

forbid (  principal,  action == JupiterStorage::Action::"UploadObject",  resource)when {  context.user_attributes.user.plan == "free"};

Resource

The resource is the bucket or object to which the action applies. Depending on the particular action, additional data will be included in the context and parent entities.

ActionResourceIncluded context
GetObjectJupiterObject{ bucket: JupiterBucket }
ListObjectsJupiterBucket
DeleteObjectJupiterObject{ bucket: JupiterBucket }
UploadObjectJupiterObject{ bucket: JupiterBucket }
DownloadObjectJupiterObject{ bucket: JupiterBucket }
StartMultipartUploadJupiterObject{ bucket: JupiterBucket }
GetMultipartUploadJupiterObject{ bucket: JupiterBucket }
UploadMultipartPartJupiterObject{ bucket: JupiterBucket }
ListMultipartUploadPartsJupiterObject{ bucket: JupiterBucket }
GetMultipartUploadPartJupiterObject{ bucket: JupiterBucket }
CompleteMultipartUploadJupiterObject{ bucket: JupiterBucket }
AbortMultipartUploadJupiterObject{ bucket: JupiterBucket }
DeleteObjectsJupiterBucket{ objects: [JupiterObject] }
CopyObjectJupiterObject{ bucket: JupiterBucket, source: JupiterObject, source_bucket: JupiterBucket }
UpdateObjectJupiterObject{ bucket: JupiterBucket }
ListMultipartUploadsJupiterBucket
UploadPartCopyJupiterObject{ bucket: JupiterBucket, source: JupiterObject }

Protect a bucket

Storage requests carry the authenticated user context supplied by Jupiter Auth. A policy can compare that context with the requested Storage resource before the operation reaches the service.

permit (  principal,  action in [    JupiterStorage::Action::"UploadObject",    JupiterStorage::Action::"GetObject"  ],  resource)when {  context.auth.user.id == resource.owner_id};

Restrict large uploads by plan

This policy denies uploads larger than 5 GB unless the authenticated user has a pro subscription plan in custom claims.

forbid (  principal,  action == JupiterStorage::Action::"UploadObject",  resource)when {  resource.object.size > 5368709120 &&  context.auth.user.custom_claims.subscription_plan != "pro"};