mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Merge pull request #85480 from tnozicka/apiserver-better-error
Add certificate identification to error message when x509 auth fails
This commit is contained in:
commit
44f5a75e6c
@ -19,8 +19,10 @@ package x509
|
||||
import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
@ -82,6 +84,27 @@ func (f UserConversionFunc) User(chain []*x509.Certificate) (*authenticator.Resp
|
||||
return f(chain)
|
||||
}
|
||||
|
||||
func columnSeparatedHex(d []byte) string {
|
||||
h := strings.ToUpper(hex.EncodeToString(d))
|
||||
var sb strings.Builder
|
||||
for i, r := range h {
|
||||
sb.WriteRune(r)
|
||||
if i%2 == 1 && i != len(h)-1 {
|
||||
sb.WriteRune(':')
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func certificateIdentifier(c *x509.Certificate) string {
|
||||
return fmt.Sprintf(
|
||||
"SN=%d, SKID=%s, AKID=%s",
|
||||
c.SerialNumber,
|
||||
columnSeparatedHex(c.SubjectKeyId),
|
||||
columnSeparatedHex(c.AuthorityKeyId),
|
||||
)
|
||||
}
|
||||
|
||||
// VerifyOptionFunc is function which provides a shallow copy of the VerifyOptions to the authenticator. This allows
|
||||
// for cases where the options (particularly the CAs) can change. If the bool is false, then the returned VerifyOptions
|
||||
// are ignored and the authenticator will express "no opinion". This allows a clear signal for cases where a CertPool
|
||||
@ -129,7 +152,11 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.R
|
||||
clientCertificateExpirationHistogram.Observe(remaining.Seconds())
|
||||
chains, err := req.TLS.PeerCertificates[0].Verify(optsCopy)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
return nil, false, fmt.Errorf(
|
||||
"verifying certificate %s failed: %w",
|
||||
certificateIdentifier(req.TLS.PeerCertificates[0]),
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
var errlist []error
|
||||
|
@ -881,6 +881,8 @@ func getCertsFromFile(t *testing.T, names ...string) []*x509.Certificate {
|
||||
}
|
||||
|
||||
func getCert(t *testing.T, pemData string) *x509.Certificate {
|
||||
t.Helper()
|
||||
|
||||
pemBlock, _ := pem.Decode([]byte(pemData))
|
||||
cert, err := x509.ParseCertificate(pemBlock.Bytes)
|
||||
if err != nil {
|
||||
@ -897,3 +899,58 @@ func getCerts(t *testing.T, pemData ...string) []*x509.Certificate {
|
||||
}
|
||||
return certs
|
||||
}
|
||||
|
||||
func TestCertificateIdentifier(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
cert *x509.Certificate
|
||||
expectedIdentifier string
|
||||
}{
|
||||
{
|
||||
name: "client cert",
|
||||
cert: getCert(t, clientCNCert),
|
||||
expectedIdentifier: "SN=1, SKID=E7:FB:1F:45:F0:71:77:AF:8C:10:4A:0A:42:03:F5:1F:1F:07:CF:DF, AKID=3D:F0:F7:30:3D:3B:EB:3A:55:68:FA:F5:43:C9:C7:AC:E1:3F:10:78",
|
||||
},
|
||||
{
|
||||
name: "nil serial",
|
||||
cert: func() *x509.Certificate {
|
||||
c := getCert(t, clientCNCert)
|
||||
c.SerialNumber = nil
|
||||
return c
|
||||
}(),
|
||||
expectedIdentifier: "SN=<nil>, SKID=E7:FB:1F:45:F0:71:77:AF:8C:10:4A:0A:42:03:F5:1F:1F:07:CF:DF, AKID=3D:F0:F7:30:3D:3B:EB:3A:55:68:FA:F5:43:C9:C7:AC:E1:3F:10:78",
|
||||
},
|
||||
{
|
||||
name: "empty SKID",
|
||||
cert: func() *x509.Certificate {
|
||||
c := getCert(t, clientCNCert)
|
||||
c.SubjectKeyId = nil
|
||||
return c
|
||||
}(),
|
||||
expectedIdentifier: "SN=1, SKID=, AKID=3D:F0:F7:30:3D:3B:EB:3A:55:68:FA:F5:43:C9:C7:AC:E1:3F:10:78",
|
||||
},
|
||||
{
|
||||
name: "empty AKID",
|
||||
cert: func() *x509.Certificate {
|
||||
c := getCert(t, clientCNCert)
|
||||
c.AuthorityKeyId = nil
|
||||
return c
|
||||
}(),
|
||||
expectedIdentifier: "SN=1, SKID=E7:FB:1F:45:F0:71:77:AF:8C:10:4A:0A:42:03:F5:1F:1F:07:CF:DF, AKID=",
|
||||
},
|
||||
{
|
||||
name: "self-signed",
|
||||
cert: getCert(t, selfSignedCert),
|
||||
expectedIdentifier: "SN=14307769263086146430, SKID=7C:AB:02:A8:45:3F:B0:28:2F:71:91:52:A2:71:EE:D9:40:2B:43:71, AKID=7C:AB:02:A8:45:3F:B0:28:2F:71:91:52:A2:71:EE:D9:40:2B:43:71",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got := certificateIdentifier(tc.cert)
|
||||
if got != tc.expectedIdentifier {
|
||||
t.Errorf("expected %q, got %q", tc.expectedIdentifier, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user