mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Merge pull request #599 from nirmata/542_feature
flag to use FQDN as CommonName in CSR
This commit is contained in:
commit
0f398e631d
5 changed files with 38 additions and 36 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue