adds tls certificate to tls config

Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
Mike Brown 2018-03-19 13:23:10 -05:00
parent cf156144bc
commit 89adb74414
2 changed files with 111 additions and 1 deletions

View File

@ -17,7 +17,7 @@
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
# Not from vendor.conf.
CRITOOL_VERSION=976680c4aa382339ccba214d1f1a88fdc8638b78
CRITOOL_VERSION=207e773f72fde8d8aed1447692d8f800a6686d6c
CRITOOL_PKG=github.com/kubernetes-incubator/cri-tools
CRITOOL_REPO=github.com/kubernetes-incubator/cri-tools

View File

@ -17,20 +17,38 @@ limitations under the License.
package server
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io"
"math"
"math/big"
"net"
"os"
"time"
"github.com/pkg/errors"
k8snet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/tools/remotecommand"
k8scert "k8s.io/client-go/util/cert"
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
"k8s.io/utils/exec"
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
)
const (
// OrganizationName is is the name of this organization, used for certificates etc.
OrganizationName = "containerd"
// CRIName is the common name of the CRI plugin
CRIName = "cri"
)
func newStreamServer(c *criService, addr, port string) (streaming.Server, error) {
if addr == "" {
a, err := k8snet.ChooseBindAddress(nil)
@ -42,6 +60,14 @@ func newStreamServer(c *criService, addr, port string) (streaming.Server, error)
config := streaming.DefaultConfig
config.Addr = net.JoinHostPort(addr, port)
runtime := newStreamRuntime(c)
tlsCert, err := newTLSCert()
if err != nil {
return nil, errors.Wrap(err, "failed to generate tls certificate for stream server")
}
config.TLSConfig = &tls.Config{
Certificates: []tls.Certificate{tlsCert},
InsecureSkipVerify: true,
}
return streaming.NewServer(config, runtime)
}
@ -112,3 +138,87 @@ func handleResizing(resize <-chan remotecommand.TerminalSize, resizeFunc func(si
}
}()
}
// newTLSCert returns a tls.certificate loaded from a newly generated
// x509certificate from a newly generated rsa public/private key pair. The
// x509certificate is self signed.
// TODO (mikebrow): replace / rewrite this function to support using CA
// signing of the cetificate. Requires a security plan for kubernetes regarding
// CRI connections / streaming, etc. For example, kubernetes could configure or
// require a CA service and pass a configuration down through CRI.
func newTLSCert() (tls.Certificate, error) {
fail := func(err error) (tls.Certificate, error) { return tls.Certificate{}, err }
var years = 1 // duration of certificate
// Generate new private key
privKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return fail(errors.Wrap(err, "private key cannot be created"))
}
// Generate pem block using the private key
keyPem := pem.EncodeToMemory(&pem.Block{
Type: k8scert.RSAPrivateKeyBlockType,
Bytes: x509.MarshalPKCS1PrivateKey(privKey),
})
// Generate a new random serial number for certificate
serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
if err != nil {
return fail(errors.Wrap(err, "failed to generate serial number"))
}
hostName, err := os.Hostname()
if err != nil {
return fail(errors.Wrap(err, "failed to get hostname"))
}
addrs, err := net.InterfaceAddrs()
if err != nil {
return fail(errors.Wrap(err, "failed to get host IP addresses"))
}
// Configure and create new certificate
tml := x509.Certificate{
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(years, 0, 0),
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: fmt.Sprintf("%s:%s:%s", OrganizationName, CRIName, hostName),
Organization: []string{OrganizationName},
},
BasicConstraintsValid: true,
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
default:
continue
}
tml.IPAddresses = append(tml.IPAddresses, ip)
tml.DNSNames = append(tml.DNSNames, ip.String())
}
cert, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &privKey.PublicKey, privKey)
if err != nil {
return fail(errors.Wrap(err, "certificate cannot be created"))
}
// Generate a pem block with the certificate
certPem := pem.EncodeToMemory(&pem.Block{
Type: k8scert.CertificateBlockType,
Bytes: cert,
})
// Load the tls certificate
tlsCert, err := tls.X509KeyPair(certPem, keyPem)
if err != nil {
return fail(errors.Wrap(err, "certificate could not be loaded"))
}
return tlsCert, nil
}