GithubHelp home page GithubHelp logo

nabsul / kcert Goto Github PK

View Code? Open in Web Editor NEW
154.0 154.0 21.0 368 KB

KCert: A Simple Let's Encrypt Manager for Kubernetes

License: MIT License

C# 88.27% Dockerfile 0.54% HTML 8.40% CSS 0.75% Smarty 2.05%

kcert's People

Contributors

blacs30 avatar nabsul avatar ptik31 avatar raighne-datature avatar renehezser avatar totemcaf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

kcert's Issues

Error: INSTALLATION FAILED: cannot re-use a name that is still in use

Using the ConfigMap option to create a certificate, seems to fail when trying to add a second host.

This succeeds: helm install 1.2.0 nabsul/kcert-configmap -n kcert --debug --set name=kcert,hosts="test1.mydomain.com"
This fails: helm install 1.2.0 nabsul/kcert-configmap -n kcert --debug --set name=kcert2,hosts="test2.mydomain.com"

Any idea why?

Renewal failed using ingress-nginx

Hi,

I can't for the life of me figure out why the certificate won't validate and get saved as a secret.
I'm on Azure, using the Ingress-NGINX Controller, which I only just installed through the AKS guide and I am able to access my pods without TLS, if I set up an ingress for it. When I'm setting up KCert with TLS, I get errors about failed renewals.

I had KCert set up on a previous cluster and it worked flawlessly, but now, using the exact same configurations as last time, it won't work.

My DNS is set up and I have verified that it has propagated.

Here's my ingress and logs:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  labels:
    kcert.dev/ingress: "managed"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - stage.kla.sh
      secretName: stage-tls
  rules:
    - host: stage.kla.sh
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-api
                port:
                  number: 80

Here's the logs from svc/kcert:

{
  "Timestamp": "2023:10:02 02:41:52.255820",
  "EventId": 60,
  "LogLevel": "Warning",
  "Category": "Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository",
  "Message": "Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.",
  "State": {
    "Message": "Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.",
    "path": "/root/.aspnet/DataProtection-Keys",
    "{OriginalFormat}": "Storing keys in a directory \u0027{path}\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.261320",
  "EventId": 62,
  "LogLevel": "Information",
  "Category": "Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager",
  "Message": "User profile is available. Using \u0027/root/.aspnet/DataProtection-Keys\u0027 as key repository; keys will not be encrypted at rest.",
  "State": {
    "Message": "User profile is available. Using \u0027/root/.aspnet/DataProtection-Keys\u0027 as key repository; keys will not be encrypted at rest.",
    "FullName": "/root/.aspnet/DataProtection-Keys",
    "{OriginalFormat}": "User profile is available. Using \u0027{FullName}\u0027 as key repository; keys will not be encrypted at rest."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.307266",
  "EventId": 58,
  "LogLevel": "Information",
  "Category": "Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager",
  "Message": "Creating key {f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a} with creation date 2023-10-02 14:41:52Z, activation date 2023-10-02 14:41:52Z, and expiration date 2023-12-31 14:41:52Z.",
  "State": {
    "Message": "Creating key {f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a} with creation date 2023-10-02 14:41:52Z, activation date 2023-10-02 14:41:52Z, and expiration date 2023-12-31 14:41:52Z.",
    "KeyId": "f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a",
    "CreationDate": "10/02/2023 14:41:52 \u002B00:00",
    "ActivationDate": "10/02/2023 14:41:52 \u002B00:00",
    "ExpirationDate": "12/31/2023 14:41:52 \u002B00:00",
    "{OriginalFormat}": "Creating key {KeyId:B} with creation date {CreationDate:u}, activation date {ActivationDate:u}, and expiration date {ExpirationDate:u}."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.314481",
  "EventId": 35,
  "LogLevel": "Warning",
  "Category": "Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager",
  "Message": "No XML encryptor configured. Key {f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a} may be persisted to storage in unencrypted form.",
  "State": {
    "Message": "No XML encryptor configured. Key {f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a} may be persisted to storage in unencrypted form.",
    "KeyId": "f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a",
    "{OriginalFormat}": "No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.318166",
  "EventId": 39,
  "LogLevel": "Information",
  "Category": "Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository",
  "Message": "Writing data to file \u0027/root/.aspnet/DataProtection-Keys/key-f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a.xml\u0027.",
  "State": {
    "Message": "Writing data to file \u0027/root/.aspnet/DataProtection-Keys/key-f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a.xml\u0027.",
    "FileName": "/root/.aspnet/DataProtection-Keys/key-f05a6c1a-a8e4-40c4-8971-23a7d31bdd7a.xml",
    "{OriginalFormat}": "Writing data to file \u0027{FileName}\u0027."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.332427",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalService",
  "Message": "Starting up renewal service.",
  "State": {
    "Message": "Starting up renewal service.",
    "{OriginalFormat}": "Starting up renewal service."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.337300",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalService",
  "Message": "Checking for certs that need renewals...",
  "State": {
    "Message": "Checking for certs that need renewals...",
    "{OriginalFormat}": "Checking for certs that need renewals..."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.355889",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.IngressMonitorService",
  "Message": "Watching for ingress is enabled",
  "State": {
    "Message": "Watching for ingress is enabled",
    "{OriginalFormat}": "Watching for ingress is enabled"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.361210",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.IngressMonitorService",
  "Message": "Watching for ingress changes",
  "State": {
    "Message": "Watching for ingress changes",
    "{OriginalFormat}": "Watching for ingress changes"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.366199",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.K8sClient",
  "Message": "Starting watch request for V1Ingress[kcert.dev/ingress=managed]",
  "State": {
    "Message": "Starting watch request for V1Ingress[kcert.dev/ingress=managed]",
    "type": "V1Ingress",
    "label": "kcert.dev/ingress=managed",
    "{OriginalFormat}": "Starting watch request for {type}[{label}]"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.379260",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.ConfigMonitorService",
  "Message": "Watching for configmaps is enabled",
  "State": {
    "Message": "Watching for configmaps is enabled",
    "{OriginalFormat}": "Watching for configmaps is enabled"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.379920",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.ConfigMonitorService",
  "Message": "Watching for configmaps changes",
  "State": {
    "Message": "Watching for configmaps changes",
    "{OriginalFormat}": "Watching for configmaps changes"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.380545",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.K8sClient",
  "Message": "Starting watch request for V1ConfigMap[kcert.dev/cert-request=request]",
  "State": {
    "Message": "Starting watch request for V1ConfigMap[kcert.dev/cert-request=request]",
    "type": "V1ConfigMap",
    "label": "kcert.dev/cert-request=request",
    "{OriginalFormat}": "Starting watch request for {type}[{label}]"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.389136",
  "EventId": 0,
  "LogLevel": "Warning",
  "Category": "Microsoft.AspNetCore.Server.Kestrel",
  "Message": "Overriding address(es) \u0027http://\u002B:80\u0027. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead.",
  "State": {
    "Message": "Overriding address(es) \u0027http://\u002B:80\u0027. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead.",
    "addresses": "http://\u002B:80",
    "{OriginalFormat}": "Overriding address(es) \u0027{addresses}\u0027. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.393837",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: http://[::]:80",
  "State": {
    "Message": "Now listening on: http://[::]:80",
    "address": "http://[::]:80",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.393874",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: http://[::]:8080",
  "State": {
    "Message": "Now listening on: http://[::]:8080",
    "address": "http://[::]:8080",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.393962",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Application started. Press Ctrl\u002BC to shut down.",
  "State": {
    "Message": "Application started. Press Ctrl\u002BC to shut down.",
    "{OriginalFormat}": "Application started. Press Ctrl\u002BC to shut down."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.393997",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Hosting environment: Production",
  "State": {
    "Message": "Hosting environment: Production",
    "envName": "Production",
    "{OriginalFormat}": "Hosting environment: {envName}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.394018",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Content root path: /app/",
  "State": {
    "Message": "Content root path: /app/",
    "contentRoot": "/app/",
    "{OriginalFormat}": "Content root path: {contentRoot}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.547276",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalService",
  "Message": "Renewal check completed.",
  "State": {
    "Message": "Renewal check completed.",
    "{OriginalFormat}": "Renewal check completed."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.547804",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalService",
  "Message": "Sleeping for 06:00:00",
  "State": {
    "Message": "Sleeping for 06:00:00",
    "renewalTime": "06:00:00",
    "{OriginalFormat}": "Sleeping for {renewalTime}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.568214",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.IngressMonitorService",
  "Message": "Ingress change event [Added] for app-app-ingress",
  "State": {
    "Message": "Ingress change event [Added] for app-app-ingress",
    "type": "Added",
    "ns": "app",
    "name": "app-ingress",
    "{OriginalFormat}": "Ingress change event [{type}] for {ns}-{name}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.572604",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Waiting for semaphore",
  "State": {
    "Message": "Waiting for semaphore",
    "{OriginalFormat}": "Waiting for semaphore"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.572634",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Starting check for changes.",
  "State": {
    "Message": "Starting check for changes.",
    "{OriginalFormat}": "Starting check for changes."
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.587005",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Processing ingress app:app-ingress",
  "State": {
    "Message": "Processing ingress app:app-ingress",
    "ns": "app",
    "n": "app-ingress",
    "{OriginalFormat}": "Processing ingress {ns}:{n}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.587066",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Processing secret stage-tls",
  "State": {
    "Message": "Processing secret stage-tls",
    "s": "stage-tls",
    "{OriginalFormat}": "Processing secret {s}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.604115",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Handling cert app - stage-tls hosts: stage.kla.sh",
  "State": {
    "Message": "Handling cert app - stage-tls hosts: stage.kla.sh",
    "ns": "app",
    "name": "stage-tls",
    "h": "stage.kla.sh",
    "{OriginalFormat}": "Handling cert {ns} - {name} hosts: {h}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:52.683335",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.KCertClient",
  "Message": "Giving challenge ingress time to propagate",
  "State": {
    "Message": "Giving challenge ingress time to propagate",
    "{OriginalFormat}": "Giving challenge ingress time to propagate"
  }
}
{
  "Timestamp": "2023:10:02 02:41:58.877374",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Initialized renewal process for secret app/stage-tls - hosts stage.kla.sh - kid https://acme-staging-v02.api.letsencrypt.org/acme/acct/120470404",
  "State": {
    "Message": "Initialized renewal process for secret app/stage-tls - hosts stage.kla.sh - kid https://acme-staging-v02.api.letsencrypt.org/acme/acct/120470404",
    "ns": "app",
    "secretName": "stage-tls",
    "hosts": "stage.kla.sh",
    "kid": "https://acme-staging-v02.api.letsencrypt.org/acme/acct/120470404",
    "{OriginalFormat}": "Initialized renewal process for secret {ns}/{secretName} - hosts {hosts} - kid {kid}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:59.096077",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Created order: pending",
  "State": {
    "Message": "Created order: pending",
    "status": "pending",
    "{OriginalFormat}": "Created order: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:59.096808",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Order https://acme-staging-v02.api.letsencrypt.org/acme/order/120470404/11324245514 created with finalizeUri https://acme-staging-v02.api.letsencrypt.org/acme/finalize/120470404/11324245514",
  "State": {
    "Message": "Order https://acme-staging-v02.api.letsencrypt.org/acme/order/120470404/11324245514 created with finalizeUri https://acme-staging-v02.api.letsencrypt.org/acme/finalize/120470404/11324245514",
    "orderUri": "https://acme-staging-v02.api.letsencrypt.org/acme/order/120470404/11324245514",
    "finalizeUri": "https://acme-staging-v02.api.letsencrypt.org/acme/finalize/120470404/11324245514",
    "{OriginalFormat}": "Order {orderUri} created with finalizeUri {finalizeUri}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:59.276130",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: pending",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: pending",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "pending",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:41:59.450700",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "TriggerChallenge https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/8634101444/hTMMqw: pending",
  "State": {
    "Message": "TriggerChallenge https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/8634101444/hTMMqw: pending",
    "challengeUri": "https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/8634101444/hTMMqw",
    "status": "pending",
    "{OriginalFormat}": "TriggerChallenge {challengeUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:42:09.623043",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: pending",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: pending",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "pending",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:42:19.798515",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "invalid",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:42:29.969204",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "invalid",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:42:40.136361",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "invalid",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:42:50.313571",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "invalid",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:43:00.486866",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
  "State": {
    "Message": "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid",
    "authUri": "https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444",
    "status": "invalid",
    "{OriginalFormat}": "Get Auth {authUri}: {status}"
  }
}
{
  "Timestamp": "2023:10:02 02:43:00.487232",
  "EventId": 0,
  "LogLevel": "Error",
  "Category": "KCert.Services.RenewalHandler",
  "Message": "Certificate renewal failed.",
  "Exception": "System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444 did not complete in time. Last Response: invalid\n   at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 105\n   at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 44",
  "State": {
    "Message": "Certificate renewal failed.",
    "{OriginalFormat}": "Certificate renewal failed."
  }
}
{
  "Timestamp": "2023:10:02 02:43:00.497070",
  "EventId": 0,
  "LogLevel": "Error",
  "Category": "KCert.Services.KCertClient",
  "Message": "Renewal failed",
  "Exception": "KCert.Models.RenewalException: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444 did not complete in time. Last Response: invalid\n ---\u003E System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444 did not complete in time. Last Response: invalid\n   at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 105\n   at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 44\n   --- End of inner exception stack trace ---\n   at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 56\n   at KCert.Services.KCertClient.RenewCertAsync(Task prev, String ns, String secretName, String[] hosts, CancellationToken tok) in /build/Services/KCertClient.cs:line 84",
  "State": {
    "Message": "Renewal failed",
    "{OriginalFormat}": "Renewal failed"
  }
}
{
  "Timestamp": "2023:10:02 02:43:00.499841",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.EmailClient",
  "Message": "Cannot send email email because it\u0027s not configured correctly",
  "State": {
    "Message": "Cannot send email email because it\u0027s not configured correctly",
    "{OriginalFormat}": "Cannot send email email because it\u0027s not configured correctly"
  }
}
{
  "Timestamp": "2023:10:02 02:43:00.499962",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "KCert.Services.CertChangeService",
  "Message": "Check for changes completed.",
  "State": {
    "Message": "Check for changes completed.",
    "{OriginalFormat}": "Check for changes completed."
  }
}

I believe the most noteworthy message is "Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/8634101444: invalid". I take it as the message from Let's Encrypt is received by KCert, but it's an invalid format?

Could you give me some guidance how to debug this further, what could be wrong, and what I can do to fix it?
Thanks!

It is not possible to set annotations className using environment variables

Hello,

It is not possible to set the ChallengeIngress.Annotations.kubernetes.io/ingress.class because when you try to do it via kubernetes environment variables the / is not an allowed character as such you end up with something like this:

  annotations:
    kubernetes.io-ingress.class: nginx-horizontal
    kubernetes.io/ingress.class: nginx

For

            - name: CHALLENGEINGRESS__USEANNOTATIONS
              value: 'true'
            - name: CHALLENGEINGRESS__ANNOTATIONS__kubernetes.io-ingress.class
              value: nginx-horizontal

In my opinion the annotation value should be its on appsettings.json field where only the value matters instead of merging the entire field to the ingress as is.

Support for non-nginx ingress controllers

I have a kubernetes cluster with traefik as the ingress controller.

When I create an ingress with label kcert.dev/ingress: managed and ingressClassName: traefik, the kcert created ingress for the acme-challenge is hardocded to ingressClassName: nginx. I believe this is hardcoded from appsettings.json, and I'm not sure how to override that via the helm chart, or if it's possible to override that.

It would be beneficial if you picked up the ingressClassName from the source ingress, or let us specify the desired ingressClassName in helm values.

Error checking for cert changes: ingresses.networking.k8s.io is forbidden

I see this error when installing cert via Helm -

{
  "Timestamp": "2022:12:31 12:35:01.679104",
  "EventId": 0,
  "LogLevel": "Error",
  "Category": "KCert.Services.KCertClient",
  "Message": "HTTP Operation failed with respones: {\u0022kind\u0022:\u0022Status\u0022,\u0022apiVersion\u0022:\u0022v1\u0022,\u0022metadata\u0022:{},\u0022status\u0022:\u0022Failure\u0022,\u0022message\u0022:\u0022ingresses.networking.k8s.io is forbidden: User \\\u0022system:serviceaccount:default:kcert\\\u0022 cannot create resource \\\u0022ingresses\\\u0022 in API group \\\u0022networking.k8s.io\\\u0022 in the namespace \\\u0022kcert\\\u0022\u0022,\u0022reason\u0022:\u0022Forbidden\u0022,\u0022details\u0022:{\u0022group\u0022:\u0022networking.k8s.io\u0022,\u0022kind\u0022:\u0022ingresses\u0022},\u0022code\u0022:403}\n",
  "Exception": "k8s.Autorest.HttpOperationException: Operation returned an invalid status code \u0027Forbidden\u0027\n   at k8s.Kubernetes.SendRequestRaw(String requestContent, HttpRequestMessage httpRequest, CancellationToken cancellationToken)\n   at k8s.AbstractKubernetes.k8s.INetworkingV1Operations.CreateNamespacedIngressWithHttpMessagesAsync(V1Ingress body, String namespaceParameter, String dryRun, String fieldManager, String fieldValidation, Nullable\u00601 pretty, IReadOnlyDictionary\u00602 customHeaders, CancellationToken cancellationToken)\n   at k8s.NetworkingV1OperationsExtensions.CreateNamespacedIngressAsync(INetworkingV1Operations operations, V1Ingress body, String namespaceParameter, String dryRun, String fieldManager, String fieldValidation, Nullable\u00601 pretty, CancellationToken cancellationToken)\n   at KCert.Services.K8sClient.CreateIngressAsync(V1Ingress ingress) in /build/Services/K8sClient.cs:line 189\n   at KCert.Services.KCertClient.AddChallengeHostsAsync(IEnumerable\u00601 hosts) in /build/Services/KCertClient.cs:line 141\n   at KCert.Services.KCertClient.RenewCertAsync(Task prev, String ns, String secretName, String[] hosts, CancellationToken tok) in /build/Services/KCertClient.cs:line 82",
  "State": {
    "Message": "HTTP Operation failed with respones: {\u0022kind\u0022:\u0022Status\u0022,\u0022apiVersion\u0022:\u0022v1\u0022,\u0022metadata\u0022:{},\u0022status\u0022:\u0022Failure\u0022,\u0022message\u0022:\u0022ingresses.networking.k8s.io is forbidden: User \\\u0022system:serviceaccount:default:kcert\\\u0022 cannot create resource \\\u0022ingresses\\\u0022 in API group \\\u0022networking.k8s.io\\\u0022 in the namespace \\\u0022kcert\\\u0022\u0022,\u0022reason\u0022:\u0022Forbidden\u0022,\u0022details\u0022:{\u0022group\u0022:\u0022networking.k8s.io\u0022,\u0022kind\u0022:\u0022ingresses\u0022},\u0022code\u0022:403}\n",
    "resp": "{\u0022kind\u0022:\u0022Status\u0022,\u0022apiVersion\u0022:\u0022v1\u0022,\u0022metadata\u0022:{},\u0022status\u0022:\u0022Failure\u0022,\u0022message\u0022:\u0022ingresses.networking.k8s.io is forbidden: User \\\u0022system:serviceaccount:default:kcert\\\u0022 cannot create resource \\\u0022ingresses\\\u0022 in API group \\\u0022networking.k8s.io\\\u0022 in the namespace \\\u0022kcert\\\u0022\u0022,\u0022reason\u0022:\u0022Forbidden\u0022,\u0022details\u0022:{\u0022group\u0022:\u0022networking.k8s.io\u0022,\u0022kind\u0022:\u0022ingresses\u0022},\u0022code\u0022:403}\n",
    "{OriginalFormat}": "HTTP Operation failed with respones: {resp}"
  }
}

Not sure if this is the cause, but I noticed that the ingress resource did not have a create verbs in the ClusterRole.yaml template. I tried creating my own clusterRole with the create value and overriding that in values.yaml but that didn't seem to work either

KCert does not support more than one ingressClass per cluster

Hello,

First let me explain my usage of kubernetes, I have a cluster with multiple namespaces each with it's own nginx-ingress (as opposed to a single ingress for the entire cluster). This is a requirement so that I can have multiple hostnames in Azure (each with it's own static IP address).

Example:

kubectl get svc --all-namespaces | grep LoadBalancer
horizontal       horizontal-ingress-nginx-controller                   LoadBalancer   10.0.83.191    51.137.10.234   80:30547/TCP,443:32055/TCP                              53d
productcatalog   productcatalogue-ingress-nginx-controller             LoadBalancer   10.0.127.146   20.82.30.223    80:30584/TCP,443:30684/TCP                              53d
sit              sit-ingress-nginx-controller                          LoadBalancer   10.0.65.221    20.71.66.71     80:31417/TCP,443:30893/TCP                              53d
telco            telco-ingress-nginx-controller                        LoadBalancer   10.0.6.40      104.45.64.105   80:30217/TCP,443:30069/TCP                              53

As such each of my Ingresses use a specific ingressClass (for example nginx-productcatalogue, nginx-sit, etc).

The problem is that when KCert detects this ingress it will create an ingress for the .well-known endpoint either using the ChallengeIngress.ClassName or ChallengeIngress.Annotations.kubernetes.io/ingress.class value (depending on the configuration).

This is problematic because, currently the only way to refresh certificates is manually setting the above variables to match the correct ingress class name so that the correct nginx exposes the .well-known endpoint in the correct host/IP.

In my opinion KCert should generate the .well-known ingresses using the value of the ingressClass of each managed ingress. This can be an option obviously to extend existing options.

Avoid dealing with ingresses altogether

Let's deal with secrets only, not ingresses. This should simply the code significantly.

Changes:

  • Add same label that ingresses have to secrets for management
  • Add ability to list all non-managed secrets to be added through the UI
  • Add another meta field for list of hosts

Feature Request | Protect Kcert UI

Hi as of now Kcert UI is pretty much open and contains no auth security anyone can renew cert and view configurations. As a feature request to implement basic auth to protect anyone accessing and renewing certs from UI.

Certificate renewal failed

Hi,
i dont know how to debug this further.
my setup is arm64 ( pine64 boards) running ubuntu and microk8s with the metallb software load balancer leading into ingress-nginx controller. then i created an nginx 'hello world' pod with persistent storage and a service and an ingress, so far works well on http.

Now i want to add tls termination on the ingress controller and found your project. this looks much cleaner then cert-manager.
so i defined the label and the tls section in the ingress definition and i see kcert responding. it tries to create secrets and get it signed, but that last part seems to fail. ''renewal failed", as you can see from the error logs below.

  • tried production url too.
  • tried longer ACME__VALIDATIONWAITTIMESECONDS 60

as soon as i define a tls section in the ingress, i get a certificate from ca 'Kubernetes Ingress Controller Fake Certificate' and it redirects http into https. i cant see my hello world message on http anymore. (perhaps thats why the challenge is unaccessible?)
i am guessing it is unable to host the challenge token on http. How does this part work and how to trace and debug this?

kubectl logs -n kcert kcert-56c78dc7cc-949hq
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalHandler","Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","State":{"Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","authUri":"https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283","status":"invalid","{OriginalFormat}":"Get Auth {authUri}: {status}"}} {"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalHandler","Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","State":{"Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","authUri":"https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283","status":"invalid","{OriginalFormat}":"Get Auth {authUri}: {status}"}} {"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalHandler","Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","State":{"Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","authUri":"https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283","status":"invalid","{OriginalFormat}":"Get Auth {authUri}: {status}"}} {"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalHandler","Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","State":{"Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","authUri":"https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283","status":"invalid","{OriginalFormat}":"Get Auth {authUri}: {status}"}} {"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalHandler","Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","State":{"Message":"Get Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283: invalid","authUri":"https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283","status":"invalid","{OriginalFormat}":"Get Auth {authUri}: {status}"}} {"EventId":0,"LogLevel":"Error","Category":"KCert.Services.RenewalHandler","Message":"Certificate renewal failed.","Exception":"System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283 did not complete in time. Last Response: invalid at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 111 at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 45","State":{"Message":"Certificate renewal failed.","{OriginalFormat}":"Certificate renewal failed."}} {"EventId":0,"LogLevel":"Error","Category":"KCert.Services.KCertClient","Message":"Renewal failed","Exception":"KCert.Models.RenewalException: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283 did not complete in time. Last Response: invalid ---\u003E System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3543724283 did not complete in time. Last Response: invalid at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 111 at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 45 --- End of inner exception stack trace --- at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 57 at KCert.Services.KCertClient.RenewCertAsync(Task prev, String ns, String secretName, String[] hosts, CancellationToken tok) in /build/Services/KCertClient.cs:line 63","State":{"Message":"Renewal failed","{OriginalFormat}":"Renewal failed"}} {"EventId":0,"LogLevel":"Information","Category":"KCert.Services.EmailClient","Message":"Cannot send email email because it\u0027s not configured correctly","State":{"Message":"Cannot send email email because it\u0027s not configured correctly","{OriginalFormat}":"Cannot send email email because it\u0027s not configured correctly"}}

Error: Auth did not complete in time

First time certification, using Digital Ocean Kubernetes 1.22.8-do.1 and:

NGINX Ingress controller
  Release:       v1.2.0
  Build:         a2514768cd282c41f39ab06bda17efefc4bd233a
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.19.10
{"EventId":0,"LogLevel":"Error","Category":"KCert.Services.RenewalHandler","Message":"Certificate renewal failed.","Exception":"System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/2314308814 did not complete in time. Last Response: invalid    at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 111    at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 45","State":{"Message":"Certificate renewal failed.","{OriginalFormat}":"Certificate renewal failed."}}
{"EventId":0,"LogLevel":"Error","Category":"KCert.Services.KCertClient","Message":"Renewal failed","Exception":"KCert.Models.RenewalException: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/2314308814 did not complete in time. Last Response: invalid  ---\u003E System.Exception: Auth https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/2314308814 did not complete in time. Last Response: invalid    at KCert.Services.RenewalHandler.ValidateAuthorizationAsync(String key, String kid, String nonce, Uri authUri) in /build/Services/RenewalHandler.cs:line 111    at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 45    --- End of inner exception stack trace ---    at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 57    at KCert.Services.KCertClient.RenewCertAsync(Task prev, String ns, String secretName, String[] hosts, CancellationToken tok) in /build/Services/KCertClient.cs:line 63","State":{"Message":"Renewal failed","{OriginalFormat}":"Renewal failed"}}

KCert Renewal of secret failed, when hosts in ingress decreased

Thank you for this repository.
I have been using kcert. It works well to create certificate.

When I changed hosts of ingress (decreased host entry from already existing), and after that in renewal time, I got email KCert Renewal of secret failed periodically.
When I delete ingress and secret of the ingress and deploy ingress again. It seems to work again and not get failure email.

Do I need to delete the secret of ingress when I changed (deleted) some host entries from ingress to match entries?

maybe I am doing wrong thing or I am using older version (v1.0.0).

Avoid duplicate error emails

Based on #40 , there appears to be situations where KCert will send the same error message multiple times.

Let's refactor that code to avoid that.

.NET versions

Hello again (and no rush on this)
I know you said you are working on an update for this project.
There are a few high findings in regards to the 1.2.0 release with version 6.0.11 for aspnet
Microsoft has released a new version of your builder images and they are currently on 6.0.24 which would resolve all findings from our scan tools (Anchore and Prisma Cloud Compute).
Mostly just a fyi for you.
Have a good day.

Why am I getting this error?

I'm using this to install kcert,

kubectl create ns kcert
helm install kcert nabsul/kcert -n kcert --debug --set acmeTermsAccepted=true,acmeEmail=[YOUR EMAIL]

but i'm getting this error

Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: error validating "": error validating data: ValidationError(Deployment.spec.template.spec.containers[0].env[2].value): invalid type for io.k8s.api.core.v1.EnvVar.value: got "array", expected "string"
helm.go:84: [debug] error validating "": error validating data: ValidationError(Deployment.spec.template.spec.containers[0].env[2].value): invalid type for io.k8s.api.core.v1.EnvVar.value: got "array", expected "string"
helm.sh/helm/v3/pkg/kube.scrubValidationError
        helm.sh/helm/v3/pkg/kube/client.go:643
helm.sh/helm/v3/pkg/kube.(*Client).Build
        helm.sh/helm/v3/pkg/kube/client.go:215
helm.sh/helm/v3/pkg/action.(*Install).RunWithContext
        helm.sh/helm/v3/pkg/action/install.go:275
main.runInstall
        helm.sh/helm/v3/cmd/helm/install.go:278
main.newInstallCmd.func2
        helm.sh/helm/v3/cmd/helm/install.go:139
github.com/spf13/cobra.(*Command).execute
        github.com/spf13/[email protected]/command.go:872
github.com/spf13/cobra.(*Command).ExecuteC
        github.com/spf13/[email protected]/command.go:990
github.com/spf13/cobra.(*Command).Execute
        github.com/spf13/[email protected]/command.go:918
main.main
        helm.sh/helm/v3/cmd/helm/helm.go:83
runtime.main
        runtime/proc.go:250
runtime.goexit
        runtime/asm_amd64.s:1571
unable to build kubernetes objects from release manifest
helm.sh/helm/v3/pkg/action.(*Install).RunWithContext
        helm.sh/helm/v3/pkg/action/install.go:277
main.runInstall
        helm.sh/helm/v3/cmd/helm/install.go:278
main.newInstallCmd.func2
        helm.sh/helm/v3/cmd/helm/install.go:139
github.com/spf13/cobra.(*Command).execute
        github.com/spf13/[email protected]/command.go:872
github.com/spf13/cobra.(*Command).ExecuteC
        github.com/spf13/[email protected]/command.go:990
github.com/spf13/cobra.(*Command).Execute
        github.com/spf13/[email protected]/command.go:918
main.main
        helm.sh/helm/v3/cmd/helm/helm.go:83
runtime.main
        runtime/proc.go:250
runtime.goexit
        runtime/asm_amd64.s:1571
INSTALLATION FAILED
main.newInstallCmd.func2
        helm.sh/helm/v3/cmd/helm/install.go:141
github.com/spf13/cobra.(*Command).execute
        github.com/spf13/[email protected]/command.go:872
github.com/spf13/cobra.(*Command).ExecuteC
        github.com/spf13/[email protected]/command.go:990
github.com/spf13/cobra.(*Command).Execute
        github.com/spf13/[email protected]/command.go:918
main.main
        helm.sh/helm/v3/cmd/helm/helm.go:83
runtime.main
        runtime/proc.go:250
runtime.goexit
        runtime/asm_amd64.s:1571

Docker images

Good day all,
Question about your docker releases. Are the 'sha' releases considered stable or would 1.2.0 be the latest stable release?
Also, how up to date is the Dockerfile in this repo?

Ability to constraint to a single namespace

Hello,

Would it be possible to add a configuration to constraint all K8S API requests to a predefined namespace ?

In our environment, we have only access to a single namespace, therefore calling ListSecretForAllNamespaces is failing since the API will deny the cluster-wide request.

Is wildcard of subdomain in ingress supported?

Thank you for this repository. I have used Kcert for kubernetes deployment.
I will need to create certificates of subdomains using wildcard.

Ingress documentation says that wild card is supported.
https://kubernetes.io/docs/concepts/services-networking/ingress/#hostname-wildcards

I want to use this using Kcert. Is Kcert support wildcard certificate issue?
I just tried but that seems to be failed.

Error
[Error]: Certificate renewal failed.
Error:

Value cannot be null. (Parameter 'uriString')

at KCert.Services.RenewalHandler.RenewCertAsync(String ns, String secretName, String[] hosts) in /build/Services/RenewalHandler.cs:line 56
at KCert.Services.KCertClient.RenewCertAsync(Task prev, String ns, String secretName, String[] hosts, CancellationToken tok) in /build/Services/KCertClient.cs:line 84

Ingress watching failed unexpectedly

I am getting email as below error

Ingress watching failed unexpectedly

The request was aborted.

at System.Net.Http.Http2Connection.ThrowRequestAborted(Exception innerException)
at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
at System.Net.Http.Http2Connection.Http2Stream.TryReadFromBuffer(Span1 buffer, Boolean partOfSyncRead) at System.Net.Http.Http2Connection.Http2Stream.ReadDataAsync(Memory1 buffer, HttpResponseMessage responseMessage, CancellationToken cancellationToken)
at k8s.LineSeparatedHttpContent.CancelableStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
at System.IO.StreamReader.ReadLineAsyncInternal()
at k8s.Watcher1.<>c.<CreateWatchEventEnumerator>b__21_1[TR](Task1 t)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke() at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- at k8s.Watcher1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at KCert.Services.K8sClient.WatchIngressesAsync(Func4 callback, CancellationToken tok) in /build/Services/K8sClient.cs:line 44
at KCert.Services.K8sClient.WatchIngressesAsync(Func`4 callback, CancellationToken tok) in /build/Services/K8sClient.cs:line 44
at KCert.Services.IngressMonitorService.WatchIngressesAsync(CancellationToken tok) in /build/Services/IngressMonitorService.cs:line 53

License

Hi there

Probably worth considering choosing a license.

Kind regards
Justin

Invite some people to try it out

@just1689 As promised, here's the project I've been toying with after giving up on cert-manager.

This is my personal take on what a minimal but useful certificate manager could look like. It installs as a simple service in your cluster, and you manage it via a simple web UI.

Note: You can deploy directly from nabsul/kcert, but the more secure thing to do would be building it yourself with the provided docker file. (you really shouldn't run random Docker images in your cluster).

Also, as a Microsoft employee, I'm very comfortable and productive in .NET, so that's the language it's written in :-)

Setup a single ingress with multiple hosts to manage

Right now KCert will add a rule to the existing ingress of a domain and then clean up afterwards.

What would be simpler is:

  • Create an ingress specific to KCert
  • Periodically scan for all ingresses/hosts
  • Update that single ingress to contain rules for all the hosts (to acme-challenge)

This way we don't have to worry about the time it takes for Kubernetes to pick up the change. The route has already been in there for a while and it's all good.

No errors shown but it does not seem to be working.

Hello,

I've been struggling with letsencrypt and cert-manager but no luck. Thankfully, I found your repo.
Thanks a lot for you work.

I have a question. I followed your instructions by configuring env vars, added the lable kcert.dev.ingress: "managed" to my ingress and ran kubectl apply -f deploy.yaml. Then I saw no error in the svc/kcert log but it does not seem to be working and I do not know what to check next.

This is the output from svc/kcert

[root@bastionhost kcert]# kl svc/kcert -n kcert
{"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory \u0027/root/.aspnet/DataProtection-Keys\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory \u0027{path}\u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}}
{"EventId":62,"LogLevel":"Information","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"User profile is available. Using \u0027/root/.aspnet/DataProtection-Keys\u0027 as key repository; keys will not be encrypted at rest.","State":{"Message":"User profile is available. Using \u0027/root/.aspnet/DataProtection-Keys\u0027 as key repository; keys will not be encrypted at rest.","FullName":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"User profile is available. Using \u0027{FullName}\u0027 as key repository; keys will not be encrypted at rest."}}
{"EventId":58,"LogLevel":"Information","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"Creating key {9cbf982e-eabf-4d4d-93b9-429717da7667} with creation date 2022-03-17 07:03:16Z, activation date 2022-03-17 07:03:16Z, and expiration date 2022-06-15 07:03:16Z.","State":{"Message":"Creating key {9cbf982e-eabf-4d4d-93b9-429717da7667} with creation date 2022-03-17 07:03:16Z, activation date 2022-03-17 07:03:16Z, and expiration date 2022-06-15 07:03:16Z.","KeyId":"9cbf982e-eabf-4d4d-93b9-429717da7667","CreationDate":"03/17/2022 07:03:16 \u002B00:00","ActivationDate":"03/17/2022 07:03:16 \u002B00:00","ExpirationDate":"06/15/2022 07:03:16 \u002B00:00","{OriginalFormat}":"Creating key {KeyId:B} with creation date {CreationDate:u}, activation date {ActivationDate:u}, and expiration date {ExpirationDate:u}."}}
{"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {9cbf982e-eabf-4d4d-93b9-429717da7667} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {9cbf982e-eabf-4d4d-93b9-429717da7667} may be persisted to storage in unencrypted form.","KeyId":"9cbf982e-eabf-4d4d-93b9-429717da7667","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}}
{"EventId":39,"LogLevel":"Information","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Writing data to file \u0027/root/.aspnet/DataProtection-Keys/key-9cbf982e-eabf-4d4d-93b9-429717da7667.xml\u0027.","State":{"Message":"Writing data to file \u0027/root/.aspnet/DataProtection-Keys/key-9cbf982e-eabf-4d4d-93b9-429717da7667.xml\u0027.","FileName":"/root/.aspnet/DataProtection-Keys/key-9cbf982e-eabf-4d4d-93b9-429717da7667.xml","{OriginalFormat}":"Writing data to file \u0027{FileName}\u0027."}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalService","Message":"Starting up renewal service.","State":{"Message":"Starting up renewal service.","{OriginalFormat}":"Starting up renewal service."}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalService","Message":"Checking for certs that need renewals...","State":{"Message":"Checking for certs that need renewals...","{OriginalFormat}":"Checking for certs that need renewals..."}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.IngressMonitorService","Message":"Watching for ingress changes","State":{"Message":"Watching for ingress changes","{OriginalFormat}":"Watching for ingress changes"}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.K8sClient","Message":"Watching for all ingresses with: kcert.dev/ingress=managed","State":{"Message":"Watching for all ingresses with: kcert.dev/ingress=managed","label":"kcert.dev/ingress=managed","{OriginalFormat}":"Watching for all ingresses with: {label}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrl\u002BC to shut down.","State":{"Message":"Application started. Press Ctrl\u002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrl\u002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: /app","State":{"Message":"Content root path: /app","contentRoot":"/app","{OriginalFormat}":"Content root path: {contentRoot}"}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalService","Message":"Renewal check completed.","State":{"Message":"Renewal check completed.","{OriginalFormat}":"Renewal check completed."}}
{"EventId":0,"LogLevel":"Information","Category":"KCert.Services.RenewalService","Message":"Sleeping for 06:00:00","State":{"Message":"Sleeping for 06:00:00","renewalTime":"06:00:00","{OriginalFormat}":"Sleeping for {renewalTime}"}}

This is the output from ingress-nginx

W0317 07:38:02.623938       8 controller.go:1306] Error getting SSL certificate "default/echo1-tls": local SSL certificate default/echo1-tls was not found. Using default certificate
I0317 07:38:02.658305       8 admission.go:149] processed ingress via admission controller {testedIngressLength:1 testedIngressTime:0.035s renderingIngressLength:1 renderingIngressTime:0s admissionTime:18.0kBs testedConfigurationSize:0.035}
I0317 07:38:02.658334       8 main.go:101] "successfully validated configuration, accepting" ingress="default/echo-ingress"
W0317 07:38:02.663518       8 backend_ssl.go:45] Error obtaining X.509 certificate: no object matching key "default/echo1-tls" in local store
W0317 07:38:02.663632       8 controller.go:1306] Error getting SSL certificate "default/echo1-tls": local SSL certificate default/echo1-tls was not found. Using default certificate
I0317 07:38:02.663690       8 controller.go:155] "Configuration changes detected, backend reload required"
I0317 07:38:02.663955       8 event.go:282] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"echo-ingress", UID:"040e7faa-237a-41c9-968c-92f399f5ab4b", APIVersion:"networking.k8s.io/v1", ResourceVersion:"72353653", FieldPath:""}): type: 'Normal' reason: 'Sync' Scheduled for sync
I0317 07:38:02.725071       8 controller.go:172] "Backend successfully reloaded"
I0317 07:38:02.725316       8 event.go:282] Event(v1.ObjectReference{Kind:"Pod", Namespace:"ingress-nginx", Name:"ingress-nginx-controller-9f48f5d74-gjsjk", UID:"30c2ebd3-6949-4f72-943b-7a18ae7486e4", APIVersion:"v1", ResourceVersion:"70160961", FieldPath:""}): type: 'Normal' reason: 'RELOAD' NGINX reload triggered due to a change in configuration

This is my ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo-ingress
  labels:
    kcert.dev.ingress: "managed"
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - echo1.utotech.vn
    secretName: echo1-tls
  rules:
  - host: echo1.utotech.vn
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echo1
            port:
              number: 80

image

It seems the certificate has not been issued yet.
Is there something I'm missing?

Thanks.

Watch ingresses failed unexpectedly error after kubernetes upgrade

I recently upgraded kubernetes from 1.24 to 1.27 in digitalOcean kubernetes.
After that I started to get error massage email (watch ingress failed unexpectedly) periodically shown below.

Manually upgrade certificates from port-forwarded dashboard seems to work.
docker image is nabsul/kcert:v1.2.0.
Is this error message affect auto update of certificate in the future?

Watch ingresses failed unexpectedly

The request was aborted.

at System.Net.Http.Http2Connection.ThrowRequestAborted(Exception innerException)
at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
at System.Net.Http.Http2Connection.Http2Stream.TryReadFromBuffer(Span1 buffer, Boolean partOfSyncRead) at System.Net.Http.Http2Connection.Http2Stream.ReadDataAsync(Memory1 buffer, HttpResponseMessage responseMessage, CancellationToken cancellationToken)
at k8s.LineSeparatedHttpContent.CancelableStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
at System.IO.StreamReader.ReadLineAsyncInternal()
at k8s.Watcher1.<>c.<CreateWatchEventEnumerator>b__21_1[TR](Task1 t)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke() at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of stack trace from previous location --- at k8s.Watcher1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at KCert.Services.K8sWatchClient.WatchInLoopAsync[T,L](String label, Func1 watch, Func3 callback) in /build/Services/K8sWatchClient.cs:line 57 at KCert.Services.K8sWatchClient.WatchInLoopAsync[T,L](String label, Func1 watch, Func3 callback) in /build/Services/K8sWatchClient.cs:line 57 at KCert.Services.K8sWatchClient.WatchIngressesAsync(Func3 callback, CancellationToken tok) in /build/Services/K8sWatchClient.cs:line 39
at KCert.Services.IngressMonitorService.WatchIngressesAsync(CancellationToken tok) in /build/Services/IngressMonitorService.cs:line 54
at KCert.Services.ExponentialBackoff.DoWithExponentialBackoffAsync(String actionName, Func`1 action, CancellationToken tok) in /build/Services/ExponentialBackoff.cs:line 29

Where issued certificate stored after issuing

Hi,
After the failure of issuing and renewing certificates with Let's encrypt and cert-manager, I have tried this kcert repository.
Issuing was successful and It seems to be working so far, though I have not yet tested the renewal of certificates after three months.
Thank you for creating,

I have a question about issued certificates. I could confirm the certificate in the browser and I could find created secrets with the same name in ingress using kubectl.
But I couldn't find certificates using kubectl.
Where they are stored? Are they in kcert namespace? or are they deleted?
I am not familiar with issuing certificates and Let's encrypt.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.