mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
certificates: support allowed usage
This commit is contained in:
parent
ee177dbbfe
commit
fb099ae385
@ -46,6 +46,12 @@ type CertificateSigningRequestSpec struct {
|
||||
// Base64-encoded PKCS#10 CSR data
|
||||
Request []byte
|
||||
|
||||
// usages specifies a set of usage contexts the key will be
|
||||
// valid for.
|
||||
// See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3
|
||||
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
|
||||
Usages []KeyUsage
|
||||
|
||||
// Information about the requesting user (if relevant)
|
||||
// See user.Info interface for details
|
||||
// +optional
|
||||
@ -96,3 +102,34 @@ type CertificateSigningRequestList struct {
|
||||
// +optional
|
||||
Items []CertificateSigningRequest
|
||||
}
|
||||
|
||||
// KeyUsages specifies valid usage contexts for keys.
|
||||
// See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3
|
||||
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
|
||||
type KeyUsage string
|
||||
|
||||
const (
|
||||
UsageSigning KeyUsage = "signing"
|
||||
UsageDigitalSignature KeyUsage = "digital signature"
|
||||
UsageContentCommittment KeyUsage = "content committment"
|
||||
UsageKeyEncipherment KeyUsage = "key encipherment"
|
||||
UsageKeyAgreement KeyUsage = "key agreement"
|
||||
UsageDataEncipherment KeyUsage = "data encipherment"
|
||||
UsageCertSign KeyUsage = "cert sign"
|
||||
UsageCRLSign KeyUsage = "crl sign"
|
||||
UsageEncipherOnly KeyUsage = "encipher only"
|
||||
UsageDecipherOnly KeyUsage = "decipher only"
|
||||
UsageAny KeyUsage = "any"
|
||||
UsageServerAuth KeyUsage = "server auth"
|
||||
UsageClientAuth KeyUsage = "client auth"
|
||||
UsageCodeSigning KeyUsage = "code signing"
|
||||
UsageEmailProtection KeyUsage = "email protection"
|
||||
UsageSMIME KeyUsage = "s/mime"
|
||||
UsageIPsecEndSystem KeyUsage = "ipsec end system"
|
||||
UsageIPsecTunnel KeyUsage = "ipsec tunnel"
|
||||
UsageIPsecUser KeyUsage = "ipsec user"
|
||||
UsageTimestamping KeyUsage = "timestamping"
|
||||
UsageOCSPSigning KeyUsage = "ocsp signing"
|
||||
UsageMicrosoftSGC KeyUsage = "microsoft sgc"
|
||||
UsageNetscapSGC KeyUsage = "netscape sgc"
|
||||
)
|
||||
|
@ -46,6 +46,12 @@ type CertificateSigningRequestSpec struct {
|
||||
// Base64-encoded PKCS#10 CSR data
|
||||
Request []byte `json:"request" protobuf:"bytes,1,opt,name=request"`
|
||||
|
||||
// allowedUsages specifies a set of usage contexts the key will be
|
||||
// valid for.
|
||||
// See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3
|
||||
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
|
||||
Usages []KeyUsage `json:"usages,omitempty" protobuf:"bytes,5,opt,name=keyUsage"`
|
||||
|
||||
// Information about the requesting user (if relevant)
|
||||
// See user.Info interface for details
|
||||
// +optional
|
||||
@ -95,3 +101,34 @@ type CertificateSigningRequestList struct {
|
||||
|
||||
Items []CertificateSigningRequest `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// KeyUsages specifies valid usage contexts for keys.
|
||||
// See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3
|
||||
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
|
||||
type KeyUsage string
|
||||
|
||||
const (
|
||||
UsageSigning KeyUsage = "signing"
|
||||
UsageDigitalSignature KeyUsage = "digital signature"
|
||||
UsageContentCommittment KeyUsage = "content committment"
|
||||
UsageKeyEncipherment KeyUsage = "key encipherment"
|
||||
UsageKeyAgreement KeyUsage = "key agreement"
|
||||
UsageDataEncipherment KeyUsage = "data encipherment"
|
||||
UsageCertSign KeyUsage = "cert sign"
|
||||
UsageCRLSign KeyUsage = "crl sign"
|
||||
UsageEncipherOnly KeyUsage = "encipher only"
|
||||
UsageDecipherOnly KeyUsage = "decipher only"
|
||||
UsageAny KeyUsage = "any"
|
||||
UsageServerAuth KeyUsage = "server auth"
|
||||
UsageClientAuth KeyUsage = "client auth"
|
||||
UsageCodeSigning KeyUsage = "code signing"
|
||||
UsageEmailProtection KeyUsage = "email protection"
|
||||
UsageSMIME KeyUsage = "s/mime"
|
||||
UsageIPsecEndSystem KeyUsage = "ipsec end system"
|
||||
UsageIPsecTunnel KeyUsage = "ipsec tunnel"
|
||||
UsageIPsecUser KeyUsage = "ipsec user"
|
||||
UsageTimestamping KeyUsage = "timestamping"
|
||||
UsageOCSPSigning KeyUsage = "ocsp signing"
|
||||
UsageMicrosoftSGC KeyUsage = "microsoft sgc"
|
||||
UsageNetscapSGC KeyUsage = "netscape sgc"
|
||||
)
|
||||
|
@ -32,6 +32,7 @@ go_library(
|
||||
"//pkg/util/workqueue:go_default_library",
|
||||
"//pkg/watch:go_default_library",
|
||||
"//vendor:github.com/cloudflare/cfssl/config",
|
||||
"//vendor:github.com/cloudflare/cfssl/helpers",
|
||||
"//vendor:github.com/cloudflare/cfssl/signer",
|
||||
"//vendor:github.com/cloudflare/cfssl/signer/local",
|
||||
"//vendor:github.com/golang/glog",
|
||||
|
@ -33,9 +33,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/workqueue"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
@ -43,6 +40,10 @@ type AutoApprover interface {
|
||||
AutoApprove(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error)
|
||||
}
|
||||
|
||||
type Signer interface {
|
||||
Sign(csr *certificates.CertificateSigningRequest) ([]byte, error)
|
||||
}
|
||||
|
||||
type CertificateController struct {
|
||||
kubeClient clientset.Interface
|
||||
|
||||
@ -53,8 +54,7 @@ type CertificateController struct {
|
||||
syncHandler func(csrKey string) error
|
||||
|
||||
approver AutoApprover
|
||||
|
||||
signer *local.Signer
|
||||
signer Signer
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
}
|
||||
@ -65,12 +65,7 @@ func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Du
|
||||
eventBroadcaster.StartLogging(glog.Infof)
|
||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.Core().Events("")})
|
||||
|
||||
// Configure cfssl signer
|
||||
// TODO: support non-default policy and remote/pkcs11 signing
|
||||
policy := &config.Signing{
|
||||
Default: config.DefaultConfig(),
|
||||
}
|
||||
ca, err := local.NewSignerFromFile(caCertFile, caKeyFile, policy)
|
||||
s, err := NewCFSSLSigner(caCertFile, caKeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,7 +73,7 @@ func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Du
|
||||
cc := &CertificateController{
|
||||
kubeClient: kubeClient,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "certificate"),
|
||||
signer: ca,
|
||||
signer: s,
|
||||
approver: approver,
|
||||
}
|
||||
|
||||
@ -209,9 +204,7 @@ func (cc *CertificateController) maybeSignCertificate(key string) error {
|
||||
// 3. Update the Status subresource
|
||||
|
||||
if csr.Status.Certificate == nil && IsCertificateRequestApproved(csr) {
|
||||
pemBytes := csr.Spec.Request
|
||||
req := signer.SignRequest{Request: string(pemBytes)}
|
||||
certBytes, err := cc.signer.Sign(req)
|
||||
certBytes, err := cc.signer.Sign(csr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
99
pkg/controller/certificates/cfssl_signer.go
Normal file
99
pkg/controller/certificates/cfssl_signer.go
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package certificates
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
certificates "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1"
|
||||
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
)
|
||||
|
||||
var onlySigningPolicy = &config.Signing{
|
||||
Default: &config.SigningProfile{
|
||||
Usage: []string{"signing"},
|
||||
Expiry: helpers.OneYear,
|
||||
ExpiryString: "8760h",
|
||||
},
|
||||
}
|
||||
|
||||
type CFSSLSigner struct {
|
||||
ca *x509.Certificate
|
||||
priv crypto.Signer
|
||||
sigAlgo x509.SignatureAlgorithm
|
||||
}
|
||||
|
||||
func NewCFSSLSigner(caFile, caKeyFile string) (*CFSSLSigner, error) {
|
||||
ca, err := ioutil.ReadFile(caFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cakey, err := ioutil.ReadFile(caKeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parsedCa, err := helpers.ParseCertificatePEM(ca)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
|
||||
password := []byte(strPassword)
|
||||
if strPassword == "" {
|
||||
password = nil
|
||||
}
|
||||
|
||||
priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Malformed private key %v", err)
|
||||
}
|
||||
return &CFSSLSigner{
|
||||
priv: priv,
|
||||
ca: parsedCa,
|
||||
sigAlgo: signer.DefaultSigAlgo(priv),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cs *CFSSLSigner) Sign(csr *certificates.CertificateSigningRequest) ([]byte, error) {
|
||||
var usages []string
|
||||
for _, usage := range csr.Spec.Usages {
|
||||
usages = append(usages, string(usage))
|
||||
}
|
||||
policy := &config.Signing{
|
||||
Default: &config.SigningProfile{
|
||||
Usage: usages,
|
||||
Expiry: helpers.OneYear,
|
||||
ExpiryString: "8760h",
|
||||
},
|
||||
}
|
||||
s, err := local.NewSigner(cs.priv, cs.ca, cs.sigAlgo, policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Sign(signer.SignRequest{
|
||||
Request: string(csr.Spec.Request),
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user