Skip to content

Support disable installer #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we rename the flag to reflect the usage ? for ex. --install-webhook-config ?

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 @@ -114,15 +111,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 @@ -145,40 +138,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