APPUiO Control API: Invitation

This resource implements the "Send Invitations" and "Accept Invitations" features.

Object

A virtual resource is chosen to allow for RBAC filtering for list operations. The Invitation is stored in a Secret resource in the backend. It may contain sensitive information such as the invitation token.

Virtual resource
apiVersion: user.appuio.io/v1
kind: Invitation
metadata:
  name: E303B166-5D66-4151-8F5F-B84BA84A7559 (1)
spec:
  note: "New employee dev1 (Delilah Vernon) starting 2020-04-01" (2)
  email: "dev1@acme.com" (3)
  # For billing entity invitations
  targetRefs:
  - apiGroup: "rbac.authorization.k8s.io"
    kind: "ClusterRoleBinding"
    name: "be-123-viewer"
    namespace: "" (4)
  # OR
  # For organization invitations
  - apiGroup: "appuio.io"
    kind: "OrganizationMembers"
    name: "members"
    namespace: "acme"
  - apiGroup: "rbac.authorization.k8s.io" (5)
    kind: "RoleBinding"
    name: "control-api:organization-admin"
    namespace: "acme" (6)
  # OR
  # For teams invitations
  - apiGroup: "appuio.io"
    kind: "Team"
    name: "dev"
    namespace: "acme"
status:
  token: "BL30rELat6Faee5OgfmmZGhnECnp5H8GCbw7PcgRlTTXW0OAJMYl5anzuIdO" (7)
  validUntil: "2020-05-01T14:00:00Z" (8)
  conditions:
  - lastTransitionTime: "2020-03-31T14:00:00Z"
    status: "True"
    type: EmailSent
  - lastTransitionTime: "2020-04-01T14:00:00Z"
    status: "True"
    message: "Redeemed by acme-dev1"
    type: Redeemed
1 The unique identifier of the invitation. The client should generate a UUID.
2 Free-form text that can be used to add a note for the owner sending the invitation.
3 The email address of the user to invitation.
4 Billing entity RBAC is cluster-scoped with resourceNames set to the billing entity ID.
5 Organization membership is tracked in the OrganizationMembers resource for clusters. Additional RBAC is required to see the Organization in the portal.
6 Organization RBAC is a namespaced RoleBinding.
7 The token that is used to accept the invitation. Generated by the API server.
8 The time until the invitation is valid. Generated by the API server.

Access Control

We use the same access control mechanism for Invitation as for Organization resources.

Invitations can only reference RoleBinding resources that the user has access to. This is enforced by the API server and mitigates privilege escalation risks.

Accepting an Invitation

Invitations can be accepted by any user in possession of the invitation token.

A virtual, create-only InvitationRedeemRequest resource exists to accept an invitation.

apiVersion: user.appuio.io/v1
kind: InvitationRedeemRequest
metadata:
  name: E303B166-5D66-4151-8F5F-B84BA84A7559 (1)
token: BL30rELat6Faee5OgfmmZGhnECnp5H8GCbw7PcgRlTTXW0OAJMYl5anzuIdO
1 Referencing the invitation resource above.

The redeem request is successful if the server returns no error.

Invitation Messages

The APPUiO Control API contains a Kubernetes controller that sends out invitation emails.

The controller reconciles Invitation resources and sends out emails for all resources that have the EmailSent condition set to False. If an email can’t be sent the EmailSent condition is set to False and the Reason is set to SendFailed. The Message field contains the error message.

SMS and other notification methods could be considered in the future.

Invitation Expiration

The APPUiO Control API contains a Kubernetes controller that removes expired invitations.

The controller reconciles Invitation resources and removes all resources that have the Redeemed condition set to False and the validUntil time has passed.