1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-29 02:45:06 +00:00

Merge pull request #599 from nirmata/542_feature

flag to use FQDN as CommonName in CSR
This commit is contained in:
shuting 2020-01-10 18:38:18 -08:00 committed by GitHub
commit 0f398e631d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 36 deletions

View file

@ -29,12 +29,12 @@ import (
var (
kubeconfig string
serverIP string
cpu bool
memory bool
webhookTimeout int
//TODO: this has been added to backward support command line arguments
// will be removed in future and the configuration will be set only via configmaps
filterK8Resources string
// User FQDN as CSR CN
fqdncn bool
)
func main() {
@ -184,7 +184,7 @@ func main() {
)
// CONFIGURE CERTIFICATES
tlsPair, err := client.InitTLSPemPair(clientConfig)
tlsPair, err := client.InitTLSPemPair(clientConfig, fqdncn)
if err != nil {
glog.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err)
}
@ -265,6 +265,8 @@ func init() {
flag.IntVar(&webhookTimeout, "webhooktimeout", 3, "timeout for webhook configurations")
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
flag.StringVar(&serverIP, "serverIP", "", "IP address where Kyverno controller runs. Only required if out-of-cluster.")
// Generate CSR with CN as FQDN due to https://github.com/nirmata/kyverno/issues/542
flag.BoolVar(&fqdncn, "fqdn-as-cn", false, "use FQDN as Common Name in CSR")
config.LogDefaultFlags()
flag.Parse()
}

View file

@ -528,8 +528,6 @@ spec:
- "--filterK8Resources=[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][*,kyverno,*]"
# customize webhook timout
# - "--webhooktimeout=4"
# open one of the profiling flag here
# - "--cpu=true"
ports:
- containerPort: 443
env:

View file

@ -10,6 +10,8 @@ There are 2 ways to configure the secure communications link between Kyverno and
Kyverno can request a CA signed certificate-key pair from `kube-controller-manager`. This method requires that the kube-controller-manager is configured to act as a certificate signer. To verify that this option is enabled for your cluster, check the command-line args for the kube-controller-manager. If `--cluster-signing-cert-file` and `--cluster-signing-key-file` are passed to the controller manager with paths to your CA's key-pair, then you can proceed to install Kyverno using this method.
**Deploying on EKS requires enabling a command-line argument `--fqdncn` in the 'kyverno' container in the deployment, due to a current limitation with the certificates returned by EKS for CSR(bug: https://github.com/awslabs/amazon-eks-ami/issues/341)**
To install Kyverno in a cluster that supports certificate signing, run the following command on a host with kubectl `cluster-admin` access:
````sh
@ -130,11 +132,6 @@ To run controller in this mode you should prepare TLS key/certificate pair for d
2. Start the controller using the following command: `sudo kyverno --kubeconfig=~/.kube/config --serverIP=<server_IP>`
# Try Kyverno without a Kubernetes cluster
The [Kyverno CLI](documentation/testing-policies.md#test-using-the-kyverno-cli) allows you to write and test policies without installing Kyverno in a Kubernetes cluster. Some features are not supported without a Kubernetes cluster.
# Filter kuberenetes resources that admission webhook should not process
The admission webhook checks if a policy is applicable on all admission requests. The kubernetes kinds that are not be processed can be filtered by adding the configmap named `init-config` in namespace `kyverno` and specifying the resources to be filtered under `data.resourceFilters`
@ -152,7 +149,8 @@ data:
```
By default we have specified Nodes, Events, APIService & SubjectAccessReview as the kinds to be skipped in the default configmap
[install.yaml](https://github.com/nirmata/kyverno/raw/master/definitions/init_configMap.yaml).
[install.yaml](https://github.com/nirmata/kyverno/raw/master/definitions/install.yaml).
---
<small>*Read Next >> [Writing Policies](/documentation/writing-policies.md)*</small>

View file

@ -18,15 +18,15 @@ import (
// InitTLSPemPair Loads or creates PEM private key and TLS certificate for webhook server.
// Created pair is stored in cluster's secret.
// Returns struct with key/certificate pair.
func (c *Client) InitTLSPemPair(configuration *rest.Config) (*tls.TlsPemPair, error) {
func (c *Client) InitTLSPemPair(configuration *rest.Config, fqdncn bool) (*tls.TlsPemPair, error) {
certProps, err := c.GetTLSCertProps(configuration)
if err != nil {
return nil, err
}
tlsPair := c.ReadTlsPair(certProps)
if tls.IsTlsPairShouldBeUpdated(tlsPair) {
if tls.IsTLSPairShouldBeUpdated(tlsPair) {
glog.Info("Generating new key/certificate pair for TLS")
tlsPair, err = c.GenerateTlsPemPair(certProps)
tlsPair, err = c.generateTLSPemPair(certProps, fqdncn)
if err != nil {
return nil, err
}
@ -40,15 +40,15 @@ func (c *Client) InitTLSPemPair(configuration *rest.Config) (*tls.TlsPemPair, er
return tlsPair, nil
}
//GenerateTlsPemPair Issues TLS certificate for webhook server using given PEM private key
//generateTlsPemPair Issues TLS certificate for webhook server using given PEM private key
// Returns signed and approved TLS certificate in PEM format
func (c *Client) GenerateTlsPemPair(props tls.TlsCertificateProps) (*tls.TlsPemPair, error) {
privateKey, err := tls.TlsGeneratePrivateKey()
func (c *Client) generateTLSPemPair(props tls.TlsCertificateProps, fqdncn bool) (*tls.TlsPemPair, error) {
privateKey, err := tls.TLSGeneratePrivateKey()
if err != nil {
return nil, err
}
certRequest, err := tls.TlsCertificateGenerateRequest(privateKey, props)
certRequest, err := tls.CertificateGenerateRequest(privateKey, props, fqdncn)
if err != nil {
return nil, fmt.Errorf("Unable to create certificate request: %v", err)
}
@ -65,7 +65,7 @@ func (c *Client) GenerateTlsPemPair(props tls.TlsCertificateProps) (*tls.TlsPemP
return &tls.TlsPemPair{
Certificate: tlsCert,
PrivateKey: tls.TlsPrivateKeyToPem(privateKey),
PrivateKey: tls.TLSPrivateKeyToPem(privateKey),
}, nil
}

View file

@ -27,13 +27,13 @@ type TlsPemPair struct {
PrivateKey []byte
}
//TlsGeneratePrivateKey Generates RSA private key
func TlsGeneratePrivateKey() (*rsa.PrivateKey, error) {
//TLSGeneratePrivateKey Generates RSA private key
func TLSGeneratePrivateKey() (*rsa.PrivateKey, error) {
return rsa.GenerateKey(rand.Reader, 2048)
}
//TlsPrivateKeyToPem Creates PEM block from private key object
func TlsPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte {
//TLSPrivateKeyToPem Creates PEM block from private key object
func TLSPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte {
privateKey := &pem.Block{
Type: "PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
@ -43,7 +43,7 @@ func TlsPrivateKeyToPem(rsaKey *rsa.PrivateKey) []byte {
}
//TlsCertificateRequestToPem Creates PEM block from raw certificate request
func TlsCertificateRequestToPem(csrRaw []byte) []byte {
func certificateRequestToPem(csrRaw []byte) []byte {
csrBlock := &pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csrRaw,
@ -52,26 +52,30 @@ func TlsCertificateRequestToPem(csrRaw []byte) []byte {
return pem.EncodeToMemory(csrBlock)
}
//TlsCertificateGenerateRequest Generates raw certificate signing request
func TlsCertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertificateProps) (*certificates.CertificateSigningRequest, error) {
//CertificateGenerateRequest Generates raw certificate signing request
func CertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertificateProps, fqdncn bool) (*certificates.CertificateSigningRequest, error) {
dnsNames := make([]string, 3)
dnsNames[0] = props.Service
dnsNames[1] = props.Service + "." + props.Namespace
// The full service name is the CommonName for the certificate
commonName := GenerateInClusterServiceName(props)
dnsNames[2] = commonName
csCommonName := props.Service
if fqdncn {
// use FQDN as CommonName as a workaournd for https://github.com/nirmata/kyverno/issues/542
csCommonName = commonName
}
var ips []net.IP
apiServerIp := net.ParseIP(props.ApiServerHost)
if apiServerIp != nil {
ips = append(ips, apiServerIp)
apiServerIP := net.ParseIP(props.ApiServerHost)
if apiServerIP != nil {
ips = append(ips, apiServerIP)
} else {
dnsNames = append(dnsNames, props.ApiServerHost)
}
csrTemplate := x509.CertificateRequest{
Subject: pkix.Name{
CommonName: props.Service, //commonName,
CommonName: csCommonName,
},
SignatureAlgorithm: x509.SHA256WithRSA,
DNSNames: dnsNames,
@ -92,7 +96,7 @@ func TlsCertificateGenerateRequest(privateKey *rsa.PrivateKey, props TlsCertific
Name: props.Service + "." + props.Namespace + ".cert-request",
},
Spec: certificates.CertificateSigningRequestSpec{
Request: TlsCertificateRequestToPem(csrBytes),
Request: certificateRequestToPem(csrBytes),
Groups: []string{"system:masters", "system:authenticated"},
Usages: []certificates.KeyUsage{
certificates.UsageDigitalSignature,
@ -110,7 +114,7 @@ func GenerateInClusterServiceName(props TlsCertificateProps) string {
}
//TlsCertificateGetExpirationDate Gets NotAfter property from raw certificate
func TlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) {
func tlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) {
block, _ := pem.Decode(certData)
if block == nil {
return nil, errors.New("Failed to decode PEM")
@ -127,13 +131,13 @@ func TlsCertificateGetExpirationDate(certData []byte) (*time.Time, error) {
// an expired certificate in a controller that has been running for a long time
const timeReserveBeforeCertificateExpiration time.Duration = time.Hour * 24 * 30 * 6 // About half a year
//IsTlsPairShouldBeUpdated checks if TLS pair has expited and needs to be updated
func IsTlsPairShouldBeUpdated(tlsPair *TlsPemPair) bool {
//IsTLSPairShouldBeUpdated checks if TLS pair has expited and needs to be updated
func IsTLSPairShouldBeUpdated(tlsPair *TlsPemPair) bool {
if tlsPair == nil {
return true
}
expirationDate, err := TlsCertificateGetExpirationDate(tlsPair.Certificate)
expirationDate, err := tlsCertificateGetExpirationDate(tlsPair.Certificate)
if err != nil {
return true
}