Skip to content

Commit

Permalink
Merge pull request #174 from mengqiy/disable_installer
Browse files Browse the repository at this point in the history
Support disable installer
  • Loading branch information
k8s-ci-robot committed Oct 19, 2018
2 parents 605dc32 + 96e4f8e commit 161208a
Show file tree
Hide file tree
Showing 18 changed files with 396 additions and 162 deletions.
16 changes: 14 additions & 2 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,24 @@ import (
var log = logf.Log.WithName("example-controller")

func main() {
var installWebhookConfig bool
flag.BoolVar(&installWebhookConfig, "install-webhook-config", false,
"enable the installer in the webhook server, so it will install webhook related resources during bootstrapping")

flag.Parse()
logf.SetLogger(logf.ZapLogger(false))
entryLog := log.WithName("entrypoint")

// Setup a Manager
entryLog.Info("setting up manager")
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
if err != nil {
entryLog.Error(err, "unable to set up overall controller manager")
os.Exit(1)
}

// Setup a new controller to Reconciler ReplicaSets
entryLog.Info("Setting up controller")
c, err := controller.New("foo-controller", mgr, controller.Options{
Reconciler: &reconcileReplicaSet{client: mgr.GetClient(), log: log.WithName("reconciler")},
})
Expand All @@ -73,6 +79,7 @@ func main() {
}

// Setup webhooks
entryLog.Info("setting up webhooks")
mutatingWebhook, err := builder.NewWebhookBuilder().
Name("mutating.k8s.io").
Mutating().
Expand All @@ -99,9 +106,11 @@ func main() {
os.Exit(1)
}

entryLog.Info("setting up webhook server")
as, err := webhook.NewServer("foo-admission-server", mgr, webhook.ServerOptions{
Port: 9876,
CertDir: "/tmp/cert",
Port: 9876,
CertDir: "/tmp/cert",
InstallWebhookConfig: installWebhookConfig,
BootstrapOptions: &webhook.BootstrapOptions{
Secret: &apitypes.NamespacedName{
Namespace: "default",
Expand All @@ -122,12 +131,15 @@ func main() {
entryLog.Error(err, "unable to create a new webhook server")
os.Exit(1)
}

entryLog.Info("registering webhooks to the webhook server")
err = as.Register(mutatingWebhook, validatingWebhook)
if err != nil {
entryLog.Error(err, "unable to register webhooks in the admission server")
os.Exit(1)
}

entryLog.Info("starting manager")
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
entryLog.Error(err, "unable to run manager")
os.Exit(1)
Expand Down
37 changes: 2 additions & 35 deletions pkg/webhook/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,9 @@ import (
"net"
"net/http"
"net/url"
"os"
"path"
"strconv"

"github.com/ghodss/yaml"

"k8s.io/api/admissionregistration/v1beta1"
admissionregistration "k8s.io/api/admissionregistration/v1beta1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -117,15 +114,11 @@ func (s *Server) setBootstrappingDefault() {
s.certProvisioner = &cert.Provisioner{
CertWriter: certWriter,
}
if s.Writer == nil {
s.Writer = os.Stdout
}
}

// installWebhookConfig writes the configuration of admissionWebhookConfiguration in yaml format if dryrun is true.
// Otherwise, it creates the the admissionWebhookConfiguration objects and service if any.
// InstallWebhookManifests creates the admissionWebhookConfiguration objects and service if any.
// It also provisions the certificate for the admission server.
func (s *Server) installWebhookConfig() error {
func (s *Server) InstallWebhookManifests() error {
// do defaulting if necessary
s.once.Do(s.setDefault)
if s.err != nil {
Expand All @@ -148,40 +141,14 @@ func (s *Server) installWebhookConfig() error {
_, err = s.certProvisioner.Provision(cert.Options{
ClientConfig: cc,
Objects: s.webhookConfigurations,
Dryrun: s.Dryrun,
})
if err != nil {
return err
}

if s.Dryrun {
// TODO: print here
// if dryrun, return the AdmissionWebhookConfiguration in yaml format.
return s.genYamlConfig(objects)
}

return batchCreateOrReplace(s.Client, objects...)
}

// genYamlConfig generates yaml config for admissionWebhookConfiguration
func (s *Server) genYamlConfig(objs []runtime.Object) error {
for _, obj := range objs {
_, err := s.Writer.Write([]byte("---"))
if err != nil {
return err
}
b, err := yaml.Marshal(obj)
if err != nil {
return err
}
_, err = s.Writer.Write(b)
if err != nil {
return err
}
}
return nil
}

func (s *Server) getClientConfig() (*admissionregistration.WebhookClientConfig, error) {
if s.Host != nil && s.Service != nil {
return nil, errors.New("URL and Service can't be set at the same time")
Expand Down
4 changes: 4 additions & 0 deletions pkg/webhook/internal/cert/generator/certgenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type Artifacts struct {
Key []byte
// PEM encoded serving certificate
Cert []byte
// PEM encoded CA private key
CAKey []byte
// PEM encoded CA certificate
CACert []byte
}
Expand All @@ -31,4 +33,6 @@ type Artifacts struct {
type CertGenerator interface {
// Generate returns a Artifacts struct.
Generate(CommonName string) (*Artifacts, error)
// SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
SetCA(caKey, caCert []byte)
}
14 changes: 14 additions & 0 deletions pkg/webhook/internal/cert/generator/fake/certgenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,37 @@ limitations under the License.
package fake

import (
"bytes"
"fmt"

"sigs.k8s.io/controller-runtime/pkg/webhook/internal/cert/generator"
)

// CertGenerator is a certGenerator for testing.
type CertGenerator struct {
CAKey []byte
CACert []byte
DNSNameToCertArtifacts map[string]*generator.Artifacts
}

var _ generator.CertGenerator = &CertGenerator{}

// SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
func (cp *CertGenerator) SetCA(CAKey, CACert []byte) {
cp.CAKey = CAKey
cp.CACert = CACert
}

// Generate generates certificates by matching a common name.
func (cp *CertGenerator) Generate(commonName string) (*generator.Artifacts, error) {
certs, found := cp.DNSNameToCertArtifacts[commonName]
if !found {
return nil, fmt.Errorf("failed to find common name %q in the certGenerator", commonName)
}
if cp.CAKey != nil && cp.CACert != nil &&
!bytes.Contains(cp.CAKey, []byte("invalid")) && !bytes.Contains(cp.CACert, []byte("invalid")) {
certs.CAKey = cp.CAKey
certs.CACert = cp.CACert
}
return certs, nil
}
63 changes: 55 additions & 8 deletions pkg/webhook/internal/cert/generator/selfsigned.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ limitations under the License.
package generator

import (
"crypto/rsa"
"crypto/x509"
"fmt"
"time"

"k8s.io/client-go/util/cert"
)
Expand All @@ -30,24 +32,42 @@ func ServiceToCommonName(serviceNamespace, serviceName string) string {

// SelfSignedCertGenerator implements the certGenerator interface.
// It provisions self-signed certificates.
type SelfSignedCertGenerator struct{}
type SelfSignedCertGenerator struct {
caKey []byte
caCert []byte
}

var _ CertGenerator = &SelfSignedCertGenerator{}

// SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
func (cp *SelfSignedCertGenerator) SetCA(caKey, caCert []byte) {
cp.caKey = caKey
cp.caCert = caCert
}

// Generate creates and returns a CA certificate, certificate and
// key for the server. serverKey and serverCert are used by the server
// to establish trust for clients, CA certificate is used by the
// client to verify the server authentication chain.
// The cert will be valid for 365 days.
func (cp *SelfSignedCertGenerator) Generate(commonName string) (*Artifacts, error) {
signingKey, err := cert.NewPrivateKey()
if err != nil {
return nil, fmt.Errorf("failed to create the CA private key: %v", err)
}
signingCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "webhook-cert-ca"}, signingKey)
if err != nil {
return nil, fmt.Errorf("failed to create the CA cert: %v", err)
var signingKey *rsa.PrivateKey
var signingCert *x509.Certificate
var valid bool
var err error

valid, signingKey, signingCert = cp.validCACert()
if !valid {
signingKey, err = cert.NewPrivateKey()
if err != nil {
return nil, fmt.Errorf("failed to create the CA private key: %v", err)
}
signingCert, err = cert.NewSelfSignedCACert(cert.Config{CommonName: "webhook-cert-ca"}, signingKey)
if err != nil {
return nil, fmt.Errorf("failed to create the CA cert: %v", err)
}
}

key, err := cert.NewPrivateKey()
if err != nil {
return nil, fmt.Errorf("failed to create the private key: %v", err)
Expand All @@ -65,6 +85,33 @@ func (cp *SelfSignedCertGenerator) Generate(commonName string) (*Artifacts, erro
return &Artifacts{
Key: cert.EncodePrivateKeyPEM(key),
Cert: cert.EncodeCertPEM(signedCert),
CAKey: cert.EncodePrivateKeyPEM(signingKey),
CACert: cert.EncodeCertPEM(signingCert),
}, nil
}

func (cp *SelfSignedCertGenerator) validCACert() (bool, *rsa.PrivateKey, *x509.Certificate) {
if !ValidCACert(cp.caKey, cp.caCert, cp.caCert, "",
time.Now().AddDate(1, 0, 0)) {
return false, nil, nil
}

var ok bool
key, err := cert.ParsePrivateKeyPEM(cp.caKey)
if err != nil {
return false, nil, nil
}
privateKey, ok := key.(*rsa.PrivateKey)
if !ok {
return false, nil, nil
}

certs, err := cert.ParseCertsPEM(cp.caCert)
if err != nil {
return false, nil, nil
}
if len(certs) != 1 {
return false, nil, nil
}
return true, privateKey, certs[0]
}
Loading

0 comments on commit 161208a

Please sign in to comment.