Repository: traefik/traefik (language: go)

Issue:
Add option to add custom attributes to ACME CSR
### Welcome!

- [x] Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
- [x] Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.

### What did you expect to see?

Hi there,

as happy traefik user I ran into the following: the company CA has a policy, that any certificate requests need to contain the attribute _emailAddress_.  The attempts to use traefik's ACME mechanism failed, because this attribute is missing in the CSR it sent to the CA via ACME. Debugging the CSR I found that there is no attribute at all except the SAN:

```
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = whoami.local.domain
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:b2:37:c9:1a:73:16:6f:b3:44:4c:27:40:63:b1:
                    ...
                    58:be:60:27:21:38:2b:08:90:4c:08:69:d0:f1:09:
                    d8:51:f1
                Exponent: 65537 (0x10001)
        Attributes:
            Requested Extensions:
                X509v3 Subject Alternative Name: 
                    DNS:whoami.local.domain
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        1f:42:af:c8:7b:5e:57:2f:ea:e4:4d:0b:18:76:8c:81:6e:21:
        ...
        96:75:da:32:c4:ce:bc:c8
```

It would be great If there could be more attributes added. Or do I miss some configuration option?

Best regards
Henri


Discussion / hints:
Hello @HenriWahl,

Thanks for the suggestion! 

 Unfortunately, this would not make it to our roadmap for a while as we are focused elsewhere.  If you or another community member would like to build it, let us know, and we will work with you to make sure you have all the information needed so that it can be merged.  

We prefer to work with our community members at the beginning of the design process so that we can make sure that we are aligned and can move quickly with the review and merge process.  Let us know here or create a PR before you start, and we will work with you there.  

Don’t forget to check out the [contributor docs](https://github.com/traefik/contributors-guide/blob/master/pr_guidelines.md) and to link the PR to this issue.
@nmengin if I understand it correctly the CSR process is done by the lego module from https://github.com/go-acme/lego, so this functionality had to be there anyway before traefik could use it?
Hey @HenriWahl,

At first glance, we thought that the lego API allowed it.
But if it doesn't allow it, indeed there is a PR to do on the lego side.
Before creating a PR, you **must** create an issue on the lego side.
lego is an independent project.

Fix patch:
diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md
index 62f091e08f..0a662e3739 100644
--- a/docs/content/https/acme.md
+++ b/docs/content/https/acme.md
@@ -832,6 +832,66 @@ certificatesResolvers:
 # ...
 ```
 
+### `profile`
+
+_Optional, Default=""_
+
+Certificate profile to use.
+
+For more information, please check out the [Let's Encrypt blog post](https://letsencrypt.org/2025/01/09/acme-profiles/) about certificate profile selection.
+
+```yaml tab="File (YAML)"
+certificatesResolvers:
+  myresolver:
+    acme:
+      # ...
+      profile: tlsserver
+      # ...
+```
+
+```toml tab="File (TOML)"
+[certificatesResolvers.myresolver.acme]
+  # ...
+  profile = "tlsserver"
+  # ...
+```
+
+```bash tab="CLI"
+# ...
+--certificatesresolvers.myresolver.acme.profile=tlsserver
+# ...
+```
+
+### `emailAddresses`
+
+_Optional, Default=""_
+
+CSR email addresses to use.
+
+```yaml tab="File (YAML)"
+certificatesResolvers:
+  myresolver:
+    acme:
+      # ...
+      emailAddresses:
+        - foo@example.com
+        - bar@example.org
+      # ...
+```
+
+```toml tab="File (TOML)"
+[certificatesResolvers.myresolver.acme]
+  # ...
+  emailAddresses = ["foo@example.com", "bar@example.org"]
+  # ...
+```
+
+```bash tab="CLI"
+# ...
+--certificatesresolvers.myresolver.acme.emailaddresses=foo@example.com,bar@example.org
+# ...
+```
+
 ### `keyType`
 
 _Optional, Default="RSA4096"_
diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md
index e963cfb683..dac410d217 100644
--- a/docs/content/reference/static-configuration/cli-ref.md
+++ b/docs/content/reference/static-configuration/cli-ref.md
@@ -168,6 +168,9 @@ Key identifier from External CA.
 `--certificatesresolvers.<name>.acme.email`:  
 Email address used for registration.
 
+`--certificatesresolvers.<name>.acme.emailaddresses`:  
+CSR email addresses to use.
+
 `--certificatesresolvers.<name>.acme.httpchallenge`:  
 Activate HTTP-01 Challenge. (Default: ```false```)
 
@@ -180,6 +183,9 @@ KeyType used for generating certificate private key. Allow value 'EC256', 'EC384
 `--certificatesresolvers.<name>.acme.preferredchain`:  
 Preferred chain to use.
 
+`--certificatesresolvers.<name>.acme.profile`:  
+Certificate profile to use.
+
 `--certificatesresolvers.<name>.acme.storage`:  
 Storage to use. (Default: ```acme.json```)
 
diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md
index b89a048e37..b67909baab 100644
--- a/docs/content/reference/static-configuration/env-ref.md
+++ b/docs/content/reference/static-configuration/env-ref.md
@@ -168,6 +168,9 @@ Key identifier from External CA.
 `TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_EMAIL`:  
 Email address used for registration.
 
+`TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_EMAILADDRESSES`:  
+CSR email addresses to use.
+
 `TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_HTTPCHALLENGE`:  
 Activate HTTP-01 Challenge. (Default: ```false```)
 
@@ -180,6 +183,9 @@ KeyType used for generating certificate private key. Allow value 'EC256', 'EC384
 `TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_PREFERREDCHAIN`:  
 Preferred chain to use.
 
+`TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_PROFILE`:  
+Certificate profile to use.
+
 `TRAEFIK_CERTIFICATESRESOLVERS_<NAME>_ACME_STORAGE`:  
 Storage to use. (Default: ```acme.json```)
 
diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml
index c379e02613..d35cf897dd 100644
--- a/docs/content/reference/static-configuration/file.toml
+++ b/docs/content/reference/static-configuration/file.toml
@@ -505,6 +505,8 @@
       email = "foobar"
       caServer = "foobar"
       preferredChain = "foobar"
+      profile = "foobar"
+      emailAddresses = ["foobar", "foobar"]
       storage = "foobar"
       keyType = "foobar"
       certificatesDuration = 42
@@ -533,6 +535,8 @@
       email = "foobar"
       caServer = "foobar"
       preferredChain = "foobar"
+      profile = "foobar"
+      emailAddresses = ["foobar", "foobar"]
       storage = "foobar"
       keyType = "foobar"
       certificatesDuration = 42
diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml
index a0a9bbf681..5b8361e08e 100644
--- a/docs/content/reference/static-configuration/file.yaml
+++ b/docs/content/reference/static-configuration/file.yaml
@@ -546,6 +546,10 @@ certificatesResolvers:
       email: foobar
       caServer: foobar
       preferredChain: foobar
+      profile: foobar
+      emailAddresses:
+        - foobar
+        - foobar
       storage: foobar
       keyType: foobar
       eab:
@@ -578,6 +582,10 @@ certificatesResolvers:
       email: foobar
       caServer: foobar
       preferredChain: foobar
+      profile: foobar
+      emailAddresses:
+        - foobar
+        - foobar
       storage: foobar
       keyType: foobar
       eab:
diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go
index 9050b529ce..9120ead27a 100644
--- a/pkg/provider/acme/provider.go
+++ b/pkg/provider/acme/provider.go
@@ -39,13 +39,15 @@ const resolverSuffix = ".acme"
 
 // Configuration holds ACME configuration provided by users.
 type Configuration struct {
-	Email                string `description:"Email address used for registration." json:"email,omitempty" toml:"email,omitempty" yaml:"email,omitempty"`
-	CAServer             string `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
-	PreferredChain       string `description:"Preferred chain to use." json:"preferredChain,omitempty" toml:"preferredChain,omitempty" yaml:"preferredChain,omitempty" export:"true"`
-	Storage              string `description:"Storage to use." json:"storage,omitempty" toml:"storage,omitempty" yaml:"storage,omitempty" export:"true"`
-	KeyType              string `description:"KeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'." json:"keyType,omitempty" toml:"keyType,omitempty" yaml:"keyType,omitempty" export:"true"`
-	EAB                  *EAB   `description:"External Account Binding to use." json:"eab,omitempty" toml:"eab,omitempty" yaml:"eab,omitempty"`
-	CertificatesDuration int    `description:"Certificates' duration in hours." json:"certificatesDuration,omitempty" toml:"certificatesDuration,omitempty" yaml:"certificatesDuration,omitempty" export:"true"`
+	Email                string   `description:"Email address used for registration." json:"email,omitempty" toml:"email,omitempty" yaml:"email,omitempty"`
+	CAServer             string   `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
+	PreferredChain       string   `description:"Preferred chain to use." json:"preferredChain,omitempty" toml:"preferredChain,omitempty" yaml:"preferredChain,omitempty" export:"true"`
+	Profile              string   `description:"Certificate profile to use." json:"profile,omitempty" toml:"profile,omitempty" yaml:"profile,omitempty" export:"true"`
+	EmailAddresses       []string `description:"CSR email addresses to use." json:"emailAddresses,omitempty" toml:"emailAddresses,omitempty" yaml:"emailAddresses,omitempty"`
+	Storage              string   `description:"Storage to use." json:"storage,omitempty" toml:"storage,omitempty" yaml:"storage,omitempty" export:"true"`
+	KeyType              string   `description:"KeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'." json:"keyType,omitempty" toml:"keyType,omitempty" yaml:"keyType,omitempty" export:"true"`
+	EAB                  *EAB     `description:"External Account Binding to use." json:"eab,omitempty" toml:"eab,omitempty" yaml:"eab,omitempty"`
+	CertificatesDuration int      `description:"Certificates' duration in hours." json:"certificatesDuration,omitempty" toml:"certificatesDuration,omitempty" yaml:"certificatesDuration,omitempty" export:"true"`
 
 	CACertificates   []string `description:"Specify the paths to PEM encoded CA Certificates that can be used to authenticate an ACME server with an HTTPS certificate not issued by a CA in the system-wide trusted root list." json:"caCertificates,omitempty" toml:"caCertificates,omitempty" yaml:"caCertificates,omitempty"`
 	CASystemCertPool bool     `description:"Define if the certificates pool must use a copy of the system cert pool." json:"caSystemCertPool,omitempty" toml:"caSystemCertPool,omitempty" yaml:"caSystemCertPool,omitempty" export:"true"`
@@ -669,6 +671,8 @@ func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []stri
 	request := certificate.ObtainRequest{
 		Domains:        domains,
 		Bundle:         true,
+		EmailAddresses: p.EmailAddresses,
+		Profile:        p.Profile,
 		PreferredChain: p.PreferredChain,
 	}
 
@@ -713,6 +717,8 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain,
 	request := certificate.ObtainRequest{
 		Domains:        domains,
 		Bundle:         true,
+		EmailAddresses: p.EmailAddresses,
+		Profile:        p.Profile,
 		PreferredChain: p.PreferredChain,
 	}
 


Test patch: