Best Practices for the JFrog Crossplane Providers

Plan names, apply order, ownership, tenancy, and GitOps for the JFrog Crossplane providers.

Plan how you structure, name, order, and own JFrog objects before you manage them at scale with the JFrog Crossplane providers.

Structure and Naming

Structure your managed resources as follows:

  • Use namespaced Kinds (*.m.crossplane.io), one namespace per team or domain. Use Kubernetes role-based access control (RBAC) to decide who may manage which JFrog objects.
  • Always write providerConfigRef with both kind and name.

Choose names carefully:

  • For most Kinds, metadata.name is the JFrog identifier, and you can't rename it later.
    • Avoid generic names (dev, my-group) on a shared JFrog Platform.
    • A managed resource adopts an existing object of the same name, reconfigures it, and deletes it when the managed resource is deleted.
  • Kubernetes names must be lowercase DNS-1123. For identifiers with uppercase or underscores (Block_High_CVEs), use a valid metadata.name and set crossplane.io/external-name before the first apply.

JFrog also applies the following naming rules.

ObjectNaming rule
Project keys2-32 lowercase alphanumerics or hyphens, starting with a letter
EnvironmentsStored as <projectKey>-<name> (32 characters in total)
Repositories assigned with projectKeyMust be named <projectKey>-...
Xray webhook namesAlphanumeric only

Apply in Order

You can apply everything at once. The providers retry references and API errors with backoff, so the system converges.

For faster, quieter rollouts, apply in waves (folders or Argo CD sync waves) and wait between them:

kubectl wait --for=condition=Ready -R -f <dir> --timeout=5m

Apply the waves in this order:

  1. Identity: users, platform groups, group membership, global roles.
  2. Projects, environments, project roles, and membership.
  3. Local and remote repositories, then virtual repositories.
  4. Permissions, cleanup policies, webhooks, replication.
  5. Xray policies, then watches, then reports.

Delete in the reverse order. Enforce that order with Usage objects. For more information, see Configure GitHub Actions OIDC and Safe Teardown with Crossplane.

Keep One Owner per Relationship

If two managed resources write the same relationship, they overwrite each other on every poll (flapping). Pick one writer for each relationship.

RelationshipPossible writersRecommendation
Group membershipArtifactory provider's User.groups, Artifactory provider's Group.usersNames, Platform provider's GroupMembers.membersPick one. With GroupMembers, put a user's groups in spec.initProvider.
Group membersPlatform provider's Group.members (deprecated, ignored) or GroupMembersUse GroupMembers.
Repository in a projectrepository projectKey or project RepositoryOne per repository
Proxy on remote repositoriesArtifactory provider's Proxy (attached by Artifactory) or repository proxySet proxy explicitly, or omit LateInitialize.
Singletons (mail server, trash can, general security, Xray settings, workers count, license, SAML, Crowd, HTTP SSO, reverse proxy, lifecycle)Any second managed resource of the KindExactly one managed resource per JFrog Platform (per project for Lifecycle)

Activate Only the Kinds You Use

In Crossplane v2, resource types can be installed as ManagedResourceDefinitions and activated by a ManagedResourceActivationPolicy.

  • The default Helm install activates everything.
  • If your platform restricts activation, activate what you need, for example *.artifactory.m.crossplane.io.
  • An inactive Kind fails with no matches for kind.

All four providers support SafeStart: controllers start when their CustomResourceDefinition (CRD) is active. The provider-artifactory provider defines more than 430 CRDs, so activating only the Kinds you use reduces API-server load.

Provider-Specific Guidance

Follow these tips for each type of JFrog object.

Local Repositories

  • Set xrayIndex: true when Xray should scan the repository.
  • Set projectKey plus projectEnvironments for project repositories.
  • includesPattern and excludesPattern are comma-separated strings.
  • For Docker, use maxUniqueTags, tagRetention, and blockPushingSchema1.

Remote Repositories

  • url is required.
  • Upstream credentials go in username plus passwordSecretRef.
  • curated: true enables JFrog Curation.
  • Many network settings are late-initialized.

Virtual Repositories

  • Every member in repositories must exist. Until then, JFrog returns Repository <key> does not exist.
  • The member order determines resolution.
  • defaultDeploymentRepo enables deploys through the virtual URL.

Federated Repositories

  • Federated repositories need several Artifactory instances reachable on their external URLs, and an Enterprise+ subscription.
  • Every member[] needs a full repository URL, including the local one.

Signed Package Types

  • For Alpine, Ansible, Debian, RPM, and Hex, create key pairs first. Name them in primaryKeypairRef and secondaryKeypairRef (plain strings).
  • Package-type availability depends on your Artifactory version. Cargo needs the Custom URL Base.

Xray

  • Create policies before watches.
  • In watchResource, set repoType: remote for remote repositories, and enable xrayIndex on watched repositories.
  • Start with notify-only actions before blockDownload or failBuild.
  • CurationPolicy needs curated remote repositories.
  • Reports are one-shot.

Access

  • Use the Platform provider's Permission (the Artifactory provider's PermissionTarget is deprecated) and GroupMembers.
  • Every principal and repository you name must exist.
  • Never manage the built-in admin user from automation.

Multi-Tenancy and GitOps

  • Grant teams RBAC on the managed resource groups they need in their namespace, for example repository.artifactory.m.crossplane.io and policy.xray.m.crossplane.io. Don't grant RBAC on configuration Kinds or singletons.
  • A namespaced managed resource can reference any ClusterProviderConfig by name. Restrict this with one of the following options:
    • Restrict spec.providerConfigRef with an admission policy (Kyverno, Gatekeeper, ValidatingAdmissionPolicy).
    • Give each namespace its own ProviderConfig with a least-privilege token.
  • Keep the provider installation (Providers, DeploymentRuntimeConfig, provider configurations) in a separate platform application from team manifests.
  • Make sure your Argo CD version has health checks for Crossplane resources, so sync waves wait for Ready.

Compositions and Usages

  • Compositions: A CompositeResourceDefinition plus a function-pipeline Composition let a platform team offer one higher-level object.
    • For example, a namespaced TeamWorkspace can render a Project, environments, a role, repositories named <projectKey>-<type>-local, a Permission, a SecurityPolicy, and a Watch.
    • Use matchControllerRef: true in selectors so composed resources reference their siblings.
    • To debug a Composition, run crossplane beta trace <kind>/<name> -n <ns>.
  • Usages: A protection.crossplane.io/v1beta1 Usage blocks deleting one resource while another resource uses it.

Next Steps


Did this page help you?