Organizations and Access

Access in PCP is described by three separate objects, and the provider declares each with its own resource. plakar_organization is the organization. plakar_member places a person or a service account in it. plakar_grant gives that member a role. A membership on its own carries no permission, so a member without a grant can sign in to the organization and do nothing in it.

Organizations

An organization is created under another one. Without parent_id, the parent is the organization the provider’s API key belongs to.

resource "plakar_organization" "lyon" {
  name = "Lyon"
}

resource "plakar_organization" "lyon_production" {
  name      = "Lyon production"
  parent_id = plakar_organization.lyon.id
}

PCP has no update operation for an organization, so the provider replaces it whenever an argument changes. Replacement deletes the organization and everything scoped to it, including its apps, schedules and members, and terraform destroy does the same. A plan that reports a plakar_organization as replaced is therefore describing the loss of its contents, not a rename.

Members

A member is either a person, identified by an email address, or a service account, identified by a name and marked with service.

resource "plakar_member" "alice" {
  organization_id = plakar_organization.lyon.id
  email           = "alice@example.com"
  name            = "Alice"
}

resource "plakar_member" "nightly" {
  organization_id = plakar_organization.lyon_production.id
  name            = "nightly-backups"
  service         = true
}

Adding a person follows the invitation path. An address that already has an account gains the membership and nothing else. A new address gets an account with a one-time password, returned in generated_password and recorded in state, which the person is required to change at their first sign-in. The account_created attribute reports which of the two happened.

A service account is an application user. It has no address and no interactive login, so its generated_password is inert and its API key is created from the web interface. This is also how the key the provider itself authenticates with comes into existence, which means the first application user cannot be created by the provider that depends on it.

Destroying a member resource removes the membership. The person’s account continues to exist, along with any membership they hold in another organization.

Grants

A grant is one pair of a subject and a role. Two roles for the same person means two grants.

resource "plakar_grant" "alice_owns_lyon" {
  organization_id = plakar_organization.lyon.id
  subject_id      = plakar_member.alice.id
  role            = "owner"
}

resource "plakar_grant" "nightly_operates" {
  organization_id = plakar_organization.lyon_production.id
  subject_id      = plakar_member.nightly.id
  role            = "operator"
}

The subject must already be a member of the organization the grant lives in. Role names come from the server’s catalogue, of which the standard tier is owner, administrator, operator and auditor.

Changing the role replaces the grant server-side and its id changes with it. A plan that reports a grant as replaced is describing a role change rather than an interruption of access.

Generated passwords

generated_password is sensitive and, like every sensitive attribute, is kept in Terraform state. It is set only for accounts that the apply registered, and is null for an address that already had one. Exposing it through an output is the usual way to hand a new account its first password:

output "initial_passwords" {
  sensitive = true
  value     = { alice = plakar_member.alice.generated_password }
}