13 KiB
CodeArtifact
Protocol: REST JSON
Endpoint: http://localhost:4566
Floci supports the CodeArtifact control plane: domains, repositories, resource policies, tags,
and public upstream (external) connections. Package publish/fetch through the CodeArtifact API
itself is implemented for the generic format only, matching AWS's own restriction that
PublishPackageVersion accepts only generic. The maven format is served through its own real
package-manager-protocol proxy (mvn/Gradle publish and resolve both work against the URL
GetRepositoryEndpoint returns); the remaining formats (npm, PyPI, NuGet, etc.) have no real
proxy behind them yet.
Supported Actions
| Action | Description |
|---|---|
CreateDomain |
Creates a domain (max 10 per account per Region), optionally with a KMS encryption key and initial tags. |
DeleteDomain |
Deletes a domain; fails with ConflictException while it still contains repositories, and with ResourceNotFoundException for a missing domain (as AWS does, although the API reference does not list it). |
DescribeDomain |
Returns a domain's full description, including its repository count. |
ListDomains |
Lists domain summaries for the account and Region, paginated. |
GetAuthorizationToken |
Issues a bearer token scoped to a domain, valid for 0 (12 hours) or 900-43200 seconds, required by the maven repository endpoint. |
PutDomainPermissionsPolicy |
Attaches or replaces a domain's resource policy, versioned by policyRevision. |
GetDomainPermissionsPolicy |
Returns a domain's current resource policy and revision. |
DeleteDomainPermissionsPolicy |
Removes a domain's resource policy, optionally checked against policyRevision. |
CreateRepository |
Creates a repository (max 1,000 per domain) with optional description, upstreams (max 10), and tags. |
DeleteRepository |
Deletes a repository. |
DescribeRepository |
Returns a repository's full description, including upstreams and external connections. |
UpdateRepository |
Updates a repository's description and/or upstream list. |
ListRepositories |
Lists repository summaries across all domains, optionally filtered by name prefix. |
ListRepositoriesInDomain |
Lists repository summaries within one domain, optionally filtered by name prefix. |
GetRepositoryEndpoint |
Returns the package-format-specific endpoint URL for a repository. |
PutRepositoryPermissionsPolicy |
Attaches or replaces a repository's resource policy, versioned by policyRevision. |
GetRepositoryPermissionsPolicy |
Returns a repository's current resource policy and revision. |
DeleteRepositoryPermissionsPolicy |
Removes a repository's resource policy, optionally checked against policyRevision. |
AssociateExternalConnection |
Attaches a fixed-catalog public upstream (e.g. public:npmjs) to a repository; mutually exclusive with repository upstreams. |
DisassociateExternalConnection |
Removes a repository's external connection. |
PublishPackageVersion |
Uploads a generic-format asset, creating or extending a package version; requires x-amz-content-sha256 and verifies it against the real hash of the bytes received. |
DescribePackageVersion |
Returns a package version's status, revision, and origin. |
GetPackageVersionAsset |
Downloads one asset from a package version by name, optionally pinned to a specific revision. |
TagResource |
Adds or updates tags on a domain or repository ARN. |
UntagResource |
Removes tags by key from a domain or repository ARN. |
ListTagsForResource |
Lists the tags on a domain or repository ARN. |
Domains and repositories are account and Region scoped and persisted through StorageFactory.
DeleteDomain fails with ConflictException while the domain still contains repositories, matching
AWS. PutDomainPermissionsPolicy/PutRepositoryPermissionsPolicy use the returned policyRevision
for optimistic locking on subsequent updates, also matching AWS. Floci enforces AWS's own account
and domain quotas: CreateDomain caps a single account at 10 domains per Region, and
CreateRepository caps a single domain at 1,000 repositories, both returning
ServiceQuotaExceededException with the offending resourceId/resourceType once reached.
AssociateExternalConnection accepts the same fixed set of AWS-hosted public upstreams
documented for real CodeArtifact (public:npmjs, public:pypi, public:maven-central, etc.) and
enforces the one-external-connection-per-repository limit AWS enforces. A repository can have
upstream repositories or an external connection, but not both, matching AWS; CreateRepository
and UpdateRepository also cap direct upstreams at 10, AWS's own repository limit.
PublishPackageVersion creates a package version in the Unfinished state when the unfinished
flag is set, and Published otherwise; once Published, a repeat publish to the same
domain/repository/package/version fails with ConflictException, matching AWS's real rule that a
published version cannot accept additional assets. Every publish returns a fresh
versionRevision, and each asset's hashes (MD5, SHA-1, SHA-256, SHA-512) are computed from
the bytes Floci actually received, not echoed from the request. Floci enforces AWS's own published
quotas for this action: a 5 GB max asset file size and a 350-asset cap per package version, both
returning ServiceQuotaExceededException.
The Maven repository endpoint
GetRepositoryEndpoint for format=maven returns http://localhost:4566/codeartifact/maven/<domain>/<repository>/.
Real Maven clients (mvn deploy, mvn dependency:get, Gradle) can publish to and resolve from
that URL directly, the same way they would against real AWS CodeArtifact; it speaks the raw Maven
repository layout (GET/PUT/HEAD over a group/artifact/version path), not the CodeArtifact JSON API.
Every request needs a token from GetAuthorizationToken scoped to the domain being accessed,
either as Authorization: Bearer <token> or as HTTP Basic with the token as the password (the
username is ignored). Basic is what a real settings.xml, configured the way
AWS documents for mvn
(<server><username>aws</username><password>${env.CODEARTIFACT_AUTH_TOKEN}</password></server>),
actually sends: Maven's HTTP wagon authenticates with Basic, not a custom header. A missing,
invalid, expired, or wrong-domain token gets a 401 challenging Basic.
It is backed by a shared Reposilite container that Floci starts lazily
on first use and reuses for every CodeArtifact repository; a CodeArtifact repository maps to its
own Reposilite repository, provisioned automatically the first time it is published to or fetched
from, and identified internally by a fresh id generated at CreateRepository time rather than a
name derived from the domain/repository, so a repository deleted and recreated under the same name
never inherits the previous one's artifacts. Two config knobs,
FLOCI_SERVICES_CODEARTIFACT_MAVEN_IMAGE and FLOCI_SERVICES_CODEARTIFACT_MAVEN_URL, pin the
image version or point at an already-running instance and skip container management, matching the
pattern used elsewhere in Floci for sidecars.
AWS-compatible failures
Domain and repository names, tags, pagination, duplicate names, missing upstreams, policy-revision
mismatches, and non-empty-domain deletes are validated. Every action also validates its required
identifiers (domain, repository, package, packageVersion, asset) are present, returning
ValidationException rather than a misleading ResourceNotFoundException for one that's simply
missing from the request. Floci returns ValidationException,
ConflictException, ResourceNotFoundException, and ServiceQuotaExceededException (tag limits)
for deterministic conditions represented by local state. ConflictException,
ResourceNotFoundException, and ServiceQuotaExceededException all carry the resourceId/
resourceType fields the wire model declares for them, matching the typed accessors the AWS SDK
exposes on those exceptions.
AWS also models AccessDeniedException, InternalServerException, and ThrottlingException.
Floci does not inject provider-side failures that cannot be derived from the request or emulator
state.
Known limitations
- Upstream cycles are not rejected.
CreateRepository/UpdateRepositoryreject a repository naming itself as its own upstream and require each named upstream to already exist, but a longer cycle (repository A has B as an upstream, B has A) is not detected. DeleteRepositorydoes not check whether other repositories still reference it as an upstream. Deleting a repository leaves any repository that named it as an upstream pointing at one that no longer exists.- Cross-account
domainOwneraddressing has no authorization check. Passing adomainOwnerthat is not the caller's own account looks up that account's domain/repository with no trust-policy or permissions-policy enforcement, consistent with Floci's IAM enforcement being opt-in elsewhere, but worth knowing if you rely on domain-sharing semantics. - Package management beyond publish/describe/get-asset isn't implemented.
ListPackages,ListPackageVersions,ListPackageVersionAssets,DeletePackageVersions,DisposePackageVersions, andUpdatePackageVersionsStatusdon't exist yet; the only way to move a version fromUnfinishedtoPublishedtoday is a follow-upPublishPackageVersioncall that omits theunfinishedflag. - The 5 GB asset size quota is nominal.
PublishPackageVersionand the Maven repository endpoint both receive the request body as a single byte array before Floci ever checks its length, so a request already large enough to exhaust available heap fails before the quota check runs. The rejection (ServiceQuotaExceededExceptionfromPublishPackageVersion, HTTP 413 from the Maven endpoint) is correct for anything that does fit in memory; it is not itself a streaming size limit. - Deleting a CodeArtifact repository does not remove its Maven artifacts. The backing Reposilite repository and everything published to it are left behind (though never reused: see above); only the CodeArtifact-side metadata is deleted. This wastes storage inside the sidecar container over a long-running Floci process but is otherwise inert, since a deleted repository's endpoint already returns 404 through the proxy regardless of what Reposilite still holds.
- Maven artifacts do not survive a Floci restart, even under persistent storage. The Reposilite
sidecar container has no volume attached and is removed on shutdown along with everything
published to it. CodeArtifact repository/domain metadata (including the stored
mavenRepositoryId) survives a restart the same way any other Floci state does under persistent storage mode; the artifacts themselves do not, so the first Maven request after a restart re-provisions an empty Reposilite repository and returns 404 for anything published before the restart. GetAuthorizationTokentokens are not revocable and are not tied to any IAM identity. Real CodeArtifact tokens are scoped to the calling principal's permissions; Floci's are scoped only to the domain named in the request; anyone who obtains one keeps the same domain-scoped access for its full lifetime.- The Maven repository endpoint does not resolve through upstream repositories or external
connections. On real CodeArtifact, a repository with another repository configured as an
upstream (
UpdateRepository'supstreams) or with anAssociateExternalConnectionto a public repository (public:maven-central, etc.) serves packages from those sources too, not just its own. Floci's Maven proxy only ever looks up the repository's own backing storage: a package that exists solely in an upstream, or only through an external connection, returns 404 through a repository that has it configured as one.
See the CodeArtifact API Reference.
Configuration
| Variable | Default | Description |
|---|---|---|
FLOCI_SERVICES_CODEARTIFACT_ENABLED |
true |
Enable or disable CodeArtifact |
FLOCI_SERVICES_CODEARTIFACT_MAVEN_IMAGE |
dzikoysk/reposilite:3.6.3 |
Reposilite image used to serve the maven format |
FLOCI_SERVICES_CODEARTIFACT_MAVEN_URL |
unset | When set, use this URL and skip Reposilite container management |
FLOCI_SERVICES_CODEARTIFACT_MAVEN_TOKEN |
unset | name:secret access token for a pre-configured MAVEN_URL |