Projects #
A project is the main isolation boundary inside an organization. It groups environments, container images, monitoring resources and access rights.
A project is a multi-tenancy soft tenant of its organization: it is identified by a short projectId (for example my-project) and is always addressed together with its organizationId.
Projects are managed through the organization controller (under the organization they belong to). Scoped API keys are managed through the org-apikey controller.
Create a project #
Creates a project and starts provisioning its external resources (Harbor project, Kubernetes namespace, ArgoCD project, monitoring).
const project = await kuzzle.query({
controller: 'organization',
action: 'createProject',
organizationId: 'paas-org-my-company',
name: 'my-project',
description: 'Customer production project'
});HTTP route:
POST /_/organizations/:organizationId/projects?name=my-projectThe response contains the created project identifiers and its Harbor credentials.
List projects #
const projects = await kuzzle.query({
controller: 'organization',
action: 'listProjects',
organizationId: 'paas-org-my-company'
});HTTP route:
GET /_/organizations/:organizationId/projectsGet a project #
const project = await kuzzle.query({
controller: 'organization',
action: 'getProject',
organizationId: 'paas-org-my-company',
projectId: 'my-project'
});HTTP route:
GET /_/organizations/:organizationId/projects/:projectIdDelete a project #
Deletes the project and tears down its external resources. Requires an owner or admin role.
await kuzzle.query({
controller: 'organization',
action: 'deleteProject',
organizationId: 'paas-org-my-company',
projectId: 'my-project'
});HTTP route:
DELETE /_/organizations/:organizationId/projects/:projectIdProject members #
Project members are organization members who are also attached to the project. A user must already belong to the organization before being attached to one of its projects. Attaching and detaching require an owner or admin role.
Kubernetes access #
A member with a federated account (@kuzzle.io) also receives Lens/kubectl access to the project namespace, at one of two levels chosen per member and per project:
| Level | Access in the namespace |
|---|---|
support (default) | read-only (paas-project-support ClusterRole) |
admin | full namespace administration (admin ClusterRole) |
The level is granted through the client role paas:project:<project id>:<level> of the cluster's OIDC client, bound in the namespace to the group oidc:paas:project:<project id>:<level>. It is revoked when the member is detached, removed from the organization, or when the project is deleted. Other accounts get no Kubernetes access through this path. If the identity provider cannot be updated, the console operation still succeeds and an operator completes the change.
Because the access groups are cluster-wide, a project id is unique across organizations: creating a project whose id is already used by another organization is refused.
List project members #
Each member carries k8sAccess: its stored Kubernetes access level, or null when none.
const members = await kuzzle.query({
controller: 'organization',
action: 'listProjectMembers',
organizationId: 'paas-org-my-company',
projectId: 'my-project'
});HTTP route:
GET /_/organizations/:organizationId/projects/:projectId/membersAttach a member to a project #
await kuzzle.query({
controller: 'organization',
action: 'addProjectMember',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
userId: 'kuid-john-doe',
k8sAccess: 'support' // optional: 'support' (default) or 'admin', federated accounts only
});HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/members?userId=kuid-john-doe&k8sAccess=supportChange the Kubernetes access of a member #
Changes the level of a federated member already attached to the project. Requires an owner or admin role. The result's synced is false when the level was stored but the identity provider could not be updated yet.
const { k8sAccess, synced } = await kuzzle.query({
controller: 'organization',
action: 'updateProjectMemberK8sAccess',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
userId: 'kuid-john-doe',
k8sAccess: 'admin'
});HTTP route:
PUT /_/organizations/:organizationId/projects/:projectId/members/:userId?k8sAccess=adminDetach a member from a project #
await kuzzle.query({
controller: 'organization',
action: 'removeProjectMember',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
userId: 'kuid-john-doe'
});HTTP route:
DELETE /_/organizations/:organizationId/projects/:projectId/members/:userIdGitHub connection #
A project can be connected to a GitHub repository, either created from an organization template or attached to an existing repository. Connecting a repository, and listing the candidate templates and repositories, requires an owner or admin role; reading the connection status is available to any project member.
The connected repository is the one the console drives for releases and deployments.
List template repositories #
Lists the repositories of the platform GitHub organization that can be used as project templates.
const templates = await kuzzle.query({
controller: 'organization',
action: 'listGithubTemplates',
organizationId: 'paas-org-my-company'
});HTTP route:
GET /_/organizations/:organizationId/github/templatesList repositories #
Lists the repositories of the platform GitHub organization, to pick an existing repository to attach.
const repositories = await kuzzle.query({
controller: 'organization',
action: 'listGithubRepositories',
organizationId: 'paas-org-my-company'
});HTTP route:
GET /_/organizations/:organizationId/github/repositoriesGet the GitHub connection status #
const status = await kuzzle.query({
controller: 'organization',
action: 'getGithubRepository',
organizationId: 'paas-org-my-company',
projectId: 'my-project'
});HTTP route:
GET /_/organizations/:organizationId/projects/:projectId/githubConnect a repository #
Create from a template:
await kuzzle.query({
controller: 'organization',
action: 'connectGithubRepository',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
templateRepo: 'template-kiotp-project',
repo: 'project-my-project' // optional, defaults to project-<projectId>
});The repository is created as a private repository of the GitHub organization. Its name is repo when given, project-<projectId> otherwise; the console pre-fills that default and lets you change it before creating. It must not already exist and may only contain letters, digits, ., - and _ (100 characters max). The KUZZLE_PAAS_PROJECT repository variable always carries the registry project, whatever the repository name.
Or attach an existing repository:
await kuzzle.query({
controller: 'organization',
action: 'connectGithubRepository',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
existingRepo: 'true',
repo: 'my-existing-repo'
});HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/githubConnecting is idempotent: calling it again with existingRepo: 'true' re-synchronizes an already attached repository (team access and repository variables).
Scoped API keys #
Scoped API keys authenticate automated access (CI/CD, the private package registry) to a single project. A key is bound to an identity (a user or a machine identity) and to the project.
Controller: org-apikey
Base HTTP route:
/_/organizations/:organizationId/projects/:projectId/api-keysCreate an API key #
Requires an owner or admin role. The secret token is returned once, in this response.
const apiKey = await kuzzle.query({
controller: 'org-apikey',
action: 'create',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
label: 'ci-deployer',
identityId: 'app-my-company-ci-deployer'
});HTTP route:
POST /_/organizations/:organizationId/projects/:projectId/api-keys?label=ci-deployeridentityId is optional and defaults to the caller.
List API keys #
Available to any project member. Never returns secrets.
const apiKeys = await kuzzle.query({
controller: 'org-apikey',
action: 'list',
organizationId: 'paas-org-my-company',
projectId: 'my-project'
});HTTP route:
GET /_/organizations/:organizationId/projects/:projectId/api-keysRevoke an API key #
Requires an owner or admin role.
await kuzzle.query({
controller: 'org-apikey',
action: 'revoke',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
apiKeyId: '<api-key-id>'
});HTTP route:
DELETE /_/organizations/:organizationId/projects/:projectId/api-keys/:apiKeyIdList registry access #
Reads the project's registry-access audit trail (who accessed the registry, and when), most recent first. Available to any project member. The optional limit caps the number of entries (default 100).
const access = await kuzzle.query({
controller: 'org-apikey',
action: 'listAccess',
organizationId: 'paas-org-my-company',
projectId: 'my-project',
limit: 50
});HTTP route:
GET /_/organizations/:organizationId/projects/:projectId/api-keys/accessResolve registry access #
Called by the private package registry, authenticated with the API key itself: it tells whether the presented key may use the registry, and which identity and project it is bound to. It takes no argument and is granted to the minimal paas-registry profile that scoped API keys carry. Each authorized call is recorded in the project's registry-access trail (see listAccess above).
// kuzzle authenticated with the scoped API key as its token
const decision = await kuzzle.query({
controller: 'registry',
action: 'resolveAccess'
});
// { authorized, identityId, organizationId, projectId, groups }HTTP route:
POST /_/registry/resolve-accessorganizationId and projectId are null, and groups is empty, when the key has no active project binding (authorized: false).
Project container images #
Container images are stored per project in the Kuzzle PaaS registry (Harbor). The deployable image versions of an application are listed through the org-application controller — see List deployable versions.