certmanager updated

This commit is contained in:
Олег Бородин
2024-08-06 18:33:12 +02:00
parent eb218c4bf6
commit c7b9532377
29 changed files with 1398 additions and 751 deletions

View File

@@ -0,0 +1,42 @@
-----BEGIN CERTIFICATE-----
MIIHZDCCBkygAwIBAgISA0TPqlhFqMMjfL8lwr1WdKCiMA0GCSqGSIb3DQEBCwUA
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
EwNSMTEwHhcNMjQwNzE1MDcwNTQyWhcNMjQxMDEzMDcwNTQxWjAYMRYwFAYDVQQD
Ew1oYW0udW5peDcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
xDw3k4983QmRIqV0PsXFfG3x1wkamrMrY9sMz+M+CR9h1iozv4OQdm5wFJp/8ert
7x+JS07v4vabYoLyVsdteRXHrqXlSDJMuZaReHIQVqKk1BYZ9miIH64ExUA6vd3r
8AmilipIPW+UJihaZnP7wPy80PUdCiq0tnSewKN+wfzka5yehWXeaTbDeDoUl1Cf
5Q3CO9KhbIYNwG8GBm+4YKiuewjjIU4sPEaCPvpvCTcwA4Lcqf1awU/nRdTLXO1e
L4LezTEPb7KSS7hEZSHs2aQbjVpoV0IcuSYI1beb7XSdsv/jDIzOpu/Sx+AqMUy+
WE4sO0Yj3ap8mbsY9HTC7QIDAQABo4IEizCCBIcwDgYDVR0PAQH/BAQDAgWgMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1Ud
DgQWBBR3smydoErE3KVUBr0/ohKZ0ghK0jAfBgNVHSMEGDAWgBTFz0ak6vTDwHps
lcQtsF6SLybjuTBXBggrBgEFBQcBAQRLMEkwIgYIKwYBBQUHMAGGFmh0dHA6Ly9y
MTEuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKGF2h0dHA6Ly9yMTEuaS5sZW5jci5v
cmcvMIICkAYDVR0RBIIChzCCAoOCEmFpcmZvcmNlLnVuaXg3Lm9yZ4IOYXJ0cy51
bml4Ny5vcmeCDWRlNC51bml4Ny5vcmeCDWRlNS51bml4Ny5vcmeCDWRlNi51bml4
Ny5vcmeCDWRlNy51bml4Ny5vcmeCDWRlYi51bml4Ny5vcmeCDWRldi51bml4Ny5v
cmeCDmRuczUudW5peDcub3Jngg1lZHUudW5peDcub3JnghBlZHVtYXgudW5peDcu
b3Jngg1naXQudW5peDcub3Jngg9nbWFpbC51bml4Ny5vcmeCDWhhbS51bml4Ny5v
cmeCDmhhc2gudW5peDcub3JnggxoZC51bml4Ny5vcmeCDmhlYXAudW5peDcub3Jn
ghJob21lZGVzay51bml4Ny5vcmeCDWh1Yi51bml4Ny5vcmeCEGl0ZGVzay51bml4
Ny5vcmeCD2xhcGlzLnVuaXg3Lm9yZ4IPbG9yZW0udW5peDcub3Jngg5tYWlsLnVu
aXg3Lm9yZ4IMbXcudW5peDcub3JnggxteC51bml4Ny5vcmeCDnBkbnMudW5peDcu
b3Jngg5waWtpLnVuaXg3Lm9yZ4IPcHJveHkudW5peDcub3JnghFyZWRtaW5lLnVu
aXg3Lm9yZ4IMcm0udW5peDcub3Jngg9zbGFjay51bml4Ny5vcmeCEHNwcmluZy51
bml4Ny5vcmeCDnNydjcudW5peDcub3JnghBzdG9yZXgudW5peDcub3JnghB0YW5h
a2gudW5peDcub3Jnggx2NS51bml4Ny5vcmeCDXcxMi51bml4Ny5vcmeCDXdjbS51
bml4Ny5vcmeCDndpa2kudW5peDcub3Jngg13d3cudW5peDcub3JnMBMGA1UdIAQM
MAowCAYGZ4EMAQIBMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHcASLDja9qmRzQP
5WoC+p0w6xxSActW3SyB2bu/qznYhHMAAAGQtW0RVQAABAMASDBGAiEAjQvvzpOR
urMOiqV5g0EuAK1A9CuAKOdWJp6/s3/SKBMCIQCbTBj13lhMnTr6bSHwoBtSwoiY
aeDJzGBmDTpbgGpFdQB1AN/hVuuqBa+1nA+GcY2owDJOrlbZbqf1pWoB0cE7vlJc
AAABkLVtEicAAAQDAEYwRAIgWe0pdXXB6UmMmeSgYLDncdkS2aKHAHDdOqKOoL9x
Kx8CIBqobR/Ve1IZMTLrRN54vh8kNmF0OkVjXtrh+ste6cKUMA0GCSqGSIb3DQEB
CwUAA4IBAQA3c88cXIejS9vy4XUow6dOuud6qqkNX1osSq2vRtYkKMZb2JVuhPAr
hQsozwptJPm5lOEDQPD8676yZNVgGdjmMvA0ewdWEp9HZ7x+RFlI7RC9CqMSOWPO
p60RMiBQlK7Els38WurmW2GzZkfykzpZZ/0lIrCNjT7aB9VjGVDOjxo/xHapHSwJ
GOxq4TTU1KaFfbFl5A2F9bRVrAAWfih+DzUzhlhZBHODzadgs2CimVYIp8gEVf1j
dGetiU2j+cvOpvQnfX7Xr8Cf2YK7E0j6lfC3RPvK9oA1bP5KBMWELXsGBrwIxgUB
f2/jRcxrQoGoEYwYW4D/JViKwelABzfc
-----END CERTIFICATE-----

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFBjCCAu6gAwIBAgIRAIp9PhPWLzDvI4a9KQdrNPgwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDEMMAoGA1UEAxMDUjExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuoe8XBsAOcvKCs3UZxD5ATylTqVhyybKUvsVAbe5KPUoHu0nsyQYOWcJ
DAjs4DqwO3cOvfPlOVRBDE6uQdaZdN5R2+97/1i9qLcT9t4x1fJyyXJqC4N0lZxG
AGQUmfOx2SLZzaiSqhwmej/+71gFewiVgdtxD4774zEJuwm+UE1fj5F2PVqdnoPy
6cRms+EGZkNIGIBloDcYmpuEMpexsr3E+BUAnSeI++JjF5ZsmydnS8TbKF5pwnnw
SVzgJFDhxLyhBax7QG0AtMJBP6dYuC/FXJuluwme8f7rsIU5/agK70XEeOtlKsLP
Xzze41xNG/cLJyuqC0J3U095ah2H2QIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
/wIBADAdBgNVHQ4EFgQUxc9GpOr0w8B6bJXELbBeki8m47kwHwYDVR0jBBgwFoAU
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
AQELBQADggIBAE7iiV0KAxyQOND1H/lxXPjDj7I3iHpvsCUf7b632IYGjukJhM1y
v4Hz/MrPU0jtvfZpQtSlET41yBOykh0FX+ou1Nj4ScOt9ZmWnO8m2OG0JAtIIE38
01S0qcYhyOE2G/93ZCkXufBL713qzXnQv5C/viOykNpKqUgxdKlEC+Hi9i2DcaR1
e9KUwQUZRhy5j/PEdEglKg3l9dtD4tuTm7kZtB8v32oOjzHTYw+7KdzdZiw/sBtn
UfhBPORNuay4pJxmY/WrhSMdzFO2q3Gu3MUBcdo27goYKjL9CTF8j/Zz55yctUoV
aneCWs/ajUX+HypkBTA+c8LGDLnWO2NKq0YD/pnARkAnYGPfUDoHR9gVSp/qRx+Z
WghiDLZsMwhN1zjtSC0uBWiugF3vTNzYIEFfaPG7Ws3jDrAMMYebQ95JQ+HIBD/R
PBuHRTBpqKlyDnkSHDHYPiNX3adPoPAcgdF3H2/W0rmoswMWgTlLn1Wu0mrks7/q
pdWfS6PJ1jty80r2VKsM/Dj3YIDfbjXKdaFU5C+8bhfJGqU3taKauuz0wHVGT3eo
6FlWkWYtbt4pgdamlwVeZEW+LM7qZEJEsMNPrfC03APKmZsJgpWCDWOKZvkZcvjV
uYkQ4omYCTX5ohy+knMjdOmdH9c7SpqEWBDC86fiNex+O0XOMEZSa8DA
-----END CERTIFICATE-----

View File

@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
-----END CERTIFICATE-----

View File

@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFVDCCBDygAwIBAgIRAKLBiJX85huxZJB/Ylc2Y5gwDQYJKoZIhvcNAQEFBQAw
gakxCzAJBgNVBAYTAnVzMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExh
a2UgQ2l0eTEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREw
DwYDVQQLEwhEU1RDQSBYMTEWMBQGA1UEAxMNRFNUIFJvb3RDQSBYMTEhMB8GCSqG
SIb3DQEJARYSY2FAZGlnc2lndHJ1c3QuY29tMB4XDTA0MDkwODE0NDM0NVoXDTA4
MTEyODEzMDI1OVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qg
Q28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+Do
M3ZJKuM/IUmTrE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwG
MoOifooUMM0RoOEqOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOe
DNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqc
kh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr
2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaOCAd4wggHaMA8GA1Ud
EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIG7BgNVHR8EgbMwgbAwga2ggaqg
gaeGgaRsZGFwOi8vbGRhcC5kaWdzaWd0cnVzdC5jb20vY249RFNUJTIwUm9vdENB
JTIwWDEsb3U9RFNUQ0ElMjBYMSxvPURpZ2l0YWwlMjBTaWduYXR1cmUlMjBUcnVz
dCUyMENvLixsPVNhbHQlMjBMYWtlJTIwQ2l0eSxTPVV0YWgsYz11cz9jZXJ0aWZp
Y2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeTCBuAYIKwYBBQUHAQEEgaswgagwgaUG
CCsGAQUFBzAChoGYbGRhcDovL2xkYXAuZGlnc2lndHJ1c3QuY29tL2NuPURTVCUy
MFJvb3RDQSUyMFgxLG91PURTVENBJTIwWDEsbz1EaWdpdGFsJTIwU2lnbmF0dXJl
JTIwVHJ1c3QlMjBDby4sbD1TYWx0JTIwTGFrZSUyMENpdHksUz1VdGFoLGM9dXM/
Y0FDZXJ0aWZpY2F0ZTtiaW5hcnkwHwYDVR0jBBgwFoAUaU2asPSCd8A2GzVVCRQa
/goSAAowHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqGSIb3DQEB
BQUAA4IBAQCpFXMtsChLFvN/Z+mwiodooamIW0qjMoVGHeN9CcDdUIGQI7cgbT10
tsJuEZx3opp2s4LoM7Gn/o0T/rysLlT34vPwI4Ei/df3aG0ite5ehqWgMuc65n1P
tadwl5JFFx3l8B0YWrOv5xJ0kY+br4FGI2OGqxagBtH2y7Uak4Iq2xipTHhlvx6a
DWAzGQHovRdLf1c4cFti11gU29QYPgDXsJSuriq3xcItGzjYZT9V45WiIlmdvez0
vCr6wcnjifctVfQ7z2o2+yl7A1+ijNhDhyfcrdPqctwx0Nk8IDitss+vNMsqoEHx
uBoIoQw0DQhKAEYri9bw+9wqZhotOjMw
-----END CERTIFICATE-----

460
pkg/cm509/x509.go Normal file
View File

@@ -0,0 +1,460 @@
package cm509
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"fmt"
"math/big"
"net"
"time"
)
type CreateIssuerPairParams struct {
CommonName string
SignerCert string
SignerKey string
}
type CreateIssuerPairResult struct {
Name string
Cert string
Key string
}
func CreateIssuerPair(params *CreateIssuerPairParams) (*CreateIssuerPairResult, error) {
var err error
res := &CreateIssuerPairResult{}
if params.SignerKey != "" && params.SignerCert == "" {
err = fmt.Errorf("The signature key and certificate must be defined together")
return res, err
}
if params.SignerKey == "" && params.SignerCert != "" {
err = fmt.Errorf("The signature key and certificate must be defined together")
return res, err
}
var signerKey any
if params.SignerKey != "" {
signerKey, err = ParseDoubleEncodedKey(params.SignerKey)
if err != nil {
return res, err
}
}
var signerCert *x509.Certificate
if params.SignerCert != "" {
signerCert, err = ParseDoubleEncodedCerificate(params.SignerCert)
if err != nil {
return res, err
}
}
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
certKey, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return res, err
}
keyPemBlock := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(certKey),
}
keyPem = pem.EncodeToMemory(keyPemBlock)
certSubject := pkix.Name{
CommonName: params.CommonName,
}
certIssuer := certSubject
if signerCert != nil {
certIssuer = signerCert.Subject
}
var issuerKey any = certKey
if signerKey != nil {
issuerKey = signerKey
}
res.Name = certSubject.String()
certTempl := &x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: certSubject,
Issuer: certIssuer,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
parentCert := certTempl
if signerCert != nil {
parentCert = signerCert
}
certBytes, err := x509.CreateCertificate(rand.Reader, certTempl, parentCert, &certKey.PublicKey, issuerKey)
if err != nil {
err := fmt.Errorf("Can't create a certificate: %v", err)
return res, err
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return res, err
}
res.Cert = base64.StdEncoding.EncodeToString(certPem)
res.Key = base64.StdEncoding.EncodeToString(keyPem)
return res, err
}
func CreateIssuerPairV0(params *CreateIssuerPairParams) (*CreateIssuerPairResult, error) {
var err error
res := &CreateIssuerPairResult{}
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return res, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
subjectName := pkix.Name{
CommonName: params.CommonName,
}
issuerName := subjectName
res.Name = subjectName.String()
certTempl := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: subjectName,
Issuer: issuerName,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &certTempl, &certTempl, &key.PublicKey, key)
if err != nil {
err := fmt.Errorf("Can't create a certificate: %v", err)
return res, err
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return res, err
}
res.Cert = base64.StdEncoding.EncodeToString(certPem)
res.Key = base64.StdEncoding.EncodeToString(keyPem)
return res, err
}
type CreateServicePairParams struct {
CommonName string
DNSNames []string
IPAddresses []string
IssuerKey string
IssuerCert string
}
type CreateServicePairResult struct {
Name string
Cert string
Key string
}
func CreateServicePairV2(params *CreateServicePairParams) (*CreateServicePairResult, error) {
var err error
res := &CreateServicePairResult{}
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return res, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
caKeyPem, err := base64.StdEncoding.DecodeString(params.IssuerKey)
if err != nil {
return res, err
}
pemBlock, _ := pem.Decode(caKeyPem)
if pemBlock == nil {
err := fmt.Errorf("Can't parse a CA private key block")
return res, err
}
caKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
if err != nil {
err := fmt.Errorf("Can't parse a CA private key")
return res, err
}
netAddresses := make([]net.IP, 0)
for _, ipAddress := range params.IPAddresses {
netAddress := net.ParseIP(ipAddress)
netAddresses = append(netAddresses, netAddress)
}
certTempl := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: pkix.Name{
CommonName: params.CommonName,
},
DNSNames: params.DNSNames,
IPAddresses: netAddresses,
IsCA: false,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &certTempl, &certTempl, &key.PublicKey, caKey)
if err != nil {
return res, fmt.Errorf("Can't create a certificate: %v", err)
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return res, err
}
res.Cert = base64.StdEncoding.EncodeToString(certPem)
res.Key = base64.StdEncoding.EncodeToString(keyPem)
return res, err
}
func ParseDoubleEncodedCerificate(certString string) (*x509.Certificate, error) {
var err error
res := &x509.Certificate{}
certPEM, err := base64.StdEncoding.DecodeString(certString)
if err != nil {
err := fmt.Errorf("Failed to parse base64 certificate string: %v", err)
return res, err
}
certBlock, _ := pem.Decode([]byte(certPEM))
if certBlock == nil {
err := fmt.Errorf("Failed to parse certificate PEM")
return res, err
}
if certBlock.Type != "CERTIFICATE" {
err := fmt.Errorf("Unknown PEM certificate type: %s", certBlock.Type)
return res, err
}
if len(certBlock.Bytes) == 0 {
err := fmt.Errorf("Empty PEM certificate block")
return res, err
}
res, err = x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return res, err
}
return res, err
}
func ParseEncodedCerificate(certPEM string) (*x509.Certificate, error) {
var err error
res := &x509.Certificate{}
certBlock, _ := pem.Decode([]byte(certPEM))
if certBlock == nil {
err := fmt.Errorf("Failed to parse certificate PEM")
return res, err
}
if certBlock.Type != "CERTIFICATE" {
err := fmt.Errorf("Unknown PEM certificate type: %s", certBlock.Type)
return res, err
}
if len(certBlock.Bytes) == 0 {
err := fmt.Errorf("Empty PEM certificate block")
return res, err
}
res, err = x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return res, err
}
return res, err
}
func ParseDoubleEncodedKey(keyString string) (any, error) {
var err error
var res any
keyPEM, err := base64.StdEncoding.DecodeString(keyString)
if err != nil {
err := fmt.Errorf("Failed to parse base64 key string: %v", err)
return res, err
}
keyBlock, _ := pem.Decode([]byte(keyPEM))
if keyBlock == nil {
err := fmt.Errorf("Failed to parse key PEM")
return res, err
}
switch keyBlock.Type {
case "PRIVATE KEY":
res, err = x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
case "RSA PRIVATE KEY":
res, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
case "EC PRIVATE KEY":
res, err = x509.ParseECPrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
default:
err := fmt.Errorf("Unknown PEM key type: %s", keyBlock.Type)
return res, err
}
return res, err
}
func ParseEncodedKey(keyPEM string) (any, error) {
var err error
var res any
keyBlock, _ := pem.Decode([]byte(keyPEM))
if keyBlock == nil {
err := fmt.Errorf("Failed to parse key PEM")
return res, err
}
switch keyBlock.Type {
case "PRIVATE KEY":
res, err = x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
case "RSA PRIVATE KEY":
res, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
case "EC PRIVATE KEY":
res, err = x509.ParseECPrivateKey(keyBlock.Bytes)
if err != nil {
return res, err
}
default:
err := fmt.Errorf("Unknown PEM key type: %s", keyBlock.Type)
return res, err
}
return res, err
}
func CheckDoubleEncodedCertificateChain(topIssuerCN string, certStrings []string) ([]string, error) {
var err error
res := make([]string, 0)
certObjs := make([]*x509.Certificate, 0)
for _, certString := range certStrings {
certObj, err := ParseDoubleEncodedCerificate(certString)
if err != nil {
return res, err
}
certObjs = append(certObjs, certObj)
}
issuerFound := false
issuerIndex := -1
for i, certObj := range certObjs {
if topIssuerCN == certObj.Subject.String() {
issuerIndex = i
issuerFound = true
}
}
if !issuerFound {
err := fmt.Errorf("Issuer for %s cannot found", topIssuerCN)
return res, err
}
interCertObj := certObjs[issuerIndex]
interCertString := certStrings[issuerIndex]
if !interCertObj.IsCA {
err := fmt.Errorf("Issuer %s is not CA", interCertObj.Subject.String())
return res, err
}
expired := interCertObj.NotAfter.Before(time.Now())
if !expired {
err := fmt.Errorf("Issuer %s expired %v", interCertObj.Subject.String(), interCertObj.NotAfter)
return res, err
}
res = append(res, interCertString)
if interCertObj.Subject.String() == interCertObj.Issuer.String() {
return res, err
}
updatedCertStrings := append(certStrings[:issuerIndex], certStrings[issuerIndex+1:]...)
topIssuerCN = interCertObj.Issuer.String()
certStringsTail, err := CheckDoubleEncodedCertificateChain(topIssuerCN, updatedCertStrings)
if err != nil {
return res, err
}
res = append(res, certStringsTail...)
return res, err
}

48
pkg/cm509/x509_test.go Normal file
View File

@@ -0,0 +1,48 @@
package cm509
import (
"encoding/base64"
"fmt"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
"sigs.k8s.io/yaml"
)
func TestCertChainCheckerErr(t *testing.T) {
var err error
certBytes, err := os.ReadFile("testchain_a01.crt")
require.NoError(t, err)
require.NotZero(t, len(certBytes))
certObj, err := ParseEncodedCerificate(string(certBytes))
require.NoError(t, err)
require.NotNil(t, certObj)
certStrings := make([]string, 0)
for i := 1; i < 4; i++ {
certBytes, err := os.ReadFile(fmt.Sprintf("testchain_a%02d.crt", i))
require.NoError(t, err)
require.NotZero(t, len(certBytes))
certString := base64.StdEncoding.EncodeToString(certBytes)
certStrings = append(certStrings, certString)
}
topIssuerCN := certObj.Issuer.String()
_, err = CheckDoubleEncodedCertificateChain(topIssuerCN, certStrings)
require.Error(t, err)
//require.NotNil(t, resString)
//require.NotZero(t, len(resString))
}
func printObj(label string, obj any) {
objBytes, _ := yaml.Marshal(obj)
objString := string(objBytes)
if strings.Count(objString, "\n") < 2 {
fmt.Printf("==== %s: %s\n", label, objString)
} else {
fmt.Printf("==== %s ::\n%s\n", label, objString)
}
}