Skip to content

Certificate profiles

A certificate profile is a named kind of certificate the CA issues, such as a TLS server certificate or a short-lived one. The draft draft-ietf-acme-profiles lets a server list its profiles in the directory and lets a client name one on a new order. Setting Config.Profiles enables it. The draft is not an RFC yet, so its wire format may still change.

Profiles: []acmeserver.Profile{
    {Name: "tls-server", Description: "TLS server certificate, valid for 90 days"},
    {Name: "short-lived", Description: "TLS server certificate, valid for 7 days"},
    {Name: "legacy", URL: "https://ca.example.com/profiles/legacy"},
},
DefaultProfile: "tls-server",

The library carries the profile name from the order to your Issuer. What a profile means, such as its key usages, extended key usages or validity, is decided by your CA.

The directory

The directory meta member gains profiles, an object that maps each name to the URL of a human-readable description:

"profiles": {
  "tls-server": "https://ca.example.com/acme/profiles/tls-server",
  "short-lived": "https://ca.example.com/acme/profiles/short-lived",
  "legacy": "https://ca.example.com/profiles/legacy"
}

A profile with a Description is described by the server itself at <BaseURL>profiles/<name>, served as text/plain to GET and HEAD. A profile with a URL points at a page you publish elsewhere. Each profile needs exactly one of the two.

A name has 1 to 64 ASCII letters, digits, dots, underscores or hyphens and starts with a letter or digit. This keeps names safe in URLs and in clients that parse the directory loosely.

Choosing a profile on an order

A new order may carry a profile member:

  • A name the server offers selects that profile.
  • No profile member selects Config.DefaultProfile, so clients without profile support keep getting the default certificate. A policy that implements ProfileChooser can pick another profile for the account. See Choosing the profile per account.
  • Any other name is refused with invalidProfile. The server never falls back to the default for a name it does not offer, because the client asked for something specific.

The order object shows the selected profile in its profile member. Order.Profile stores it. Policy.NewOrder cannot change it. IssueRequest.Profile tells the issuer which profile to apply.

Clients send the member in different ways. Certbot sends --required-profile always and --preferred-profile only when the directory lists that name. lego has --profile, acme.sh has --cert-profile and cert-manager has spec.acme.profile on the issuer.

Choosing the profile per account

A host may let some accounts use only some profiles, for example the profiles an external account binding allows. Refuse other profiles in Policy.NewOrder. A client that names no profile would then be refused whenever the default is not allowed. A policy that also implements ProfileChooser picks the profile for such an order instead:

func (p customerPolicy) DefaultProfile(ctx context.Context, account *acmeserver.Account) (string, error) {
    allowed := p.customers.Profiles(ctx, account.ExternalAccountID)
    if len(allowed) == 0 || slices.Contains(allowed, "tls-server") {
        return "", nil
    }
    return allowed[0], nil
}

An empty answer selects Config.DefaultProfile. Policy.NewOrder sees the chosen profile and can still refuse it. A returned *Problem refuses the order. Any other error, or a profile the server does not offer, is answered with serverInternal. DefaultProfile is not called for an order that names a profile.

Changing the profile list

Profiles are read from Config when the server is created. When you remove a profile, orders created under it are refused with invalidProfile at finalization. Orders already finalized continue. The draft recommends keeping a profile until the orders that use it have expired, which Config.OrderLifetime bounds.

Orders created while Config.Profiles was empty have no profile. They finalize normally after you add profiles. IssueRequest.Profile is empty for them.

Without Config.Profiles, the directory has no profiles member and a new order that names a profile is refused with invalidProfile.

Renewal

The draft does not tie a profile to renewal. A client that renews sends the profile it is configured with, which can differ from the profile of the certificate it replaces. Certbot and acme.sh store the profile in their renewal configuration. A renewal without a profile gets the default.