nabsul / kcert Goto Github PK
View Code? Open in Web Editor NEWKCert: A Simple Let's Encrypt Manager for Kubernetes
License: MIT License
KCert: A Simple Let's Encrypt Manager for Kubernetes
License: MIT License
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?
Make sure it's up to date with the helm chart
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!
There should be a way to create certs without create Ingresses.
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.
Figure out how to get certs for ingresses in different namespaces.
https://github.com/nabsul/kcert/blob/main/charts/kcert/templates/070-Deployment.yaml#L59-L65
The condition {{- if .Values.acmeKey }}
is true with the provided values.yaml. This results in a section where the secret ref name is NULL which fails to deploy.
Overriding it with acmeKey=false
in my own values.yaml works as a workaround.
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.
Was wondering if I can configure to use KCert for ZeroSSL using External Account Binding. Would be amazing if it can be!
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
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.
Let's deal with secrets only, not ingresses. This should simply the code significantly.
Changes:
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.
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.
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"}}
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"}}
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).
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.
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.
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
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?
Add link to terms url
Make sure it's being used
Renew certs automatically when there's less than 30 days to expiration.
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.
Hi! First - thanks for a cool project!
Are there any plans to support watching Istio Gateway-objects rather than just Kubernetes ingresses?
The current implementation doesn't work well together with Istio unless you strictly use Ingress
'es, which removes a fair bit of the feature-set that istio provides through its gateway abstraction.
https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/
From what I can tell, this solution works off changes to Ingress. We are trying to find a solution that allows us to tell the automated cert solution to add/remove domains directly, without having to modify Ingress. Is this possible?
Support ARM builds as well.
Hi,
as stated in your documentation kcert does expect following annotation:
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
but newer versions of nginx-ingress changed to:
spec:
ingressClassName: nginx
see also: https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/
Any consideration to support both ways since I wasn't able to generate tls certificate with the latest cert-manager.
Thx a lot
/david
Ref: #41
Ref: #85
To allow users to set any of the various environment variables that KCert supports, the simplest thing to do is add an optional env
key-value variable in the values.yaml file. This will allow users to override environment variables as they need.
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
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(Memory
1 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](Task
1 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.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at KCert.Services.K8sClient.WatchIngressesAsync(Func
4 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
Hi there
Probably worth considering choosing a license.
Kind regards
Justin
@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 :-)
Right now KCert will add a rule to the existing ingress of a domain and then clean up afterwards.
What would be simpler is:
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.
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
It seems the certificate has not been issued yet.
Is there something I'm missing?
Thanks.
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(Memory
1 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](Task
1 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.Watcher
1.CreateWatchEventEnumerator(Func1 streamReaderCreator, Action
1 onError, CancellationToken cancellationToken)+MoveNext()
at k8s.Watcher1.CreateWatchEventEnumerator(Func
1 streamReaderCreator, Action1 onError, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at KCert.Services.K8sWatchClient.WatchInLoopAsync[T,L](String label, Func
1 watch, Func3 callback) in /build/Services/K8sWatchClient.cs:line 57 at KCert.Services.K8sWatchClient.WatchInLoopAsync[T,L](String label, Func
1 watch, Func3 callback) in /build/Services/K8sWatchClient.cs:line 57 at KCert.Services.K8sWatchClient.WatchIngressesAsync(Func
3 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
Can a flow be added to support DNS challenges (needed for wildcard certs)
There's an issue with the kcertImage version value - it is set to 1.2.0 while there is none in the docker repository.
(It needs to be set to 'latest' for now, I assume)
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.
In
https://github.com/nabsul/kcert/blob/main/charts/kcert/templates/060-RoleBinding.yaml#L5
Is a copy/paste error that prevents the chart to be deployed on a different namespace than kcert.
Must be namespace: {{ .Release.Namespace | default "default" }}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.