Skip to content

cert provisioner #22

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
Jun 21, 2018
Merged

cert provisioner #22

merged 3 commits into from
Jun 21, 2018

Conversation

mengqiy
Copy link
Member

@mengqiy mengqiy commented Jun 12, 2018

@mengqiy mengqiy requested a review from pwittrock June 12, 2018 07:08
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jun 12, 2018
@mengqiy mengqiy requested a review from droot June 12, 2018 07:15
Copy link
Contributor

@droot droot left a comment

Choose a reason for hiding this comment

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

lets discuss this in person today to go over it.

limitations under the License.
*/

package certoutput
Copy link
Contributor

Choose a reason for hiding this comment

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

certio ?

@mengqiy mengqiy force-pushed the webhook branch 2 times, most recently from cd79900 to 62cad9b Compare June 12, 2018 21:33
@mengqiy
Copy link
Member Author

mengqiy commented Jun 12, 2018

PTAL

The package will write self-signed certificates to secrets.

// Build a CertProvisioner with empty options
cp := &CertProvisioner{Client: getClientOrDie(), Options: Options{}}
Copy link
Contributor

Choose a reason for hiding this comment

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

They shouldn't have to specify Options. I don't think the getClientOrDie() function is correct. Use the one from the config package

// handler error
}

If the above mutatingWebhookConfiguration is processed, the cert provisioner will provision
Copy link
Contributor

Choose a reason for hiding this comment

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

mutatingWebhookConfiguration

cap?


If the above mutatingWebhookConfiguration is processed, the cert provisioner will provision
the certificate and create an secret named "secret-foo" in namespace "namespace-bar" for webhook "webhook-1".
Similarly, it will create an secret named "secret-baz" in namespace "default" for webhook "webhook-2".
Copy link
Contributor

Choose a reason for hiding this comment

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

Also mention that it will write the CA back to the WebhookConfiguration

ServerCertName = "cert.pem"
)

// Options are options for configure a CertOutput.
Copy link
Contributor

Choose a reason for hiding this comment

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

for configuring


// Options are options for configure a CertOutput.
type Options struct {
Type *Type
Copy link
Contributor

Choose a reason for hiding this comment

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

Document Type

}

// getClientOrDie get the default client for the CertProvisioner.
func getClientOrDie() client.Client {
Copy link
Contributor

Choose a reason for hiding this comment

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

This already exists in the config package

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't find it.
There is no method returning client.Client in https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client/config
The only relevant thing I can find is client.New() method at https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/client#New


func (bc *CertProvisioner) init() {
if bc.Client == nil {
bc.Client = getClientOrDie()
Copy link
Contributor

Choose a reason for hiding this comment

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

We probably want to return an error from the calling method instead of panic-ing.

"github.com/kubernetes-sigs/controller-runtime/pkg/client/config"
)

// CertProvisioner provisions certificates for webhook configurations.
Copy link
Contributor

Choose a reason for hiding this comment

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

and writes them to an output destination - such as a Secret or local file. CertProvisioner can update the CA field of
certain resources with the CA of the certs.

}

// New builds a new CertsOutput instance for the provided webhook configuration.
func New(webhookConfig runtime.Object, client client.Client, cp certinput.CertInput, op Options) (CertsOutput, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can the Input be an option tool? Can we default it to selfsigned?

}

// New builds a new CertsOutput instance for the provided webhook configuration.
func New(webhookConfig runtime.Object, client client.Client, cp certinput.CertInput, op Options) (CertsOutput, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

For client, WDYT of injecting it?

Copy link
Member Author

Choose a reason for hiding this comment

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

What will it look like? Some pseudo code will be helpful.

@mengqiy mengqiy force-pushed the webhook branch 2 times, most recently from fa1ac99 to 952db43 Compare June 13, 2018 20:23
@mengqiy
Copy link
Member Author

mengqiy commented Jun 13, 2018

PTAL

Copy link
Contributor

@droot droot left a comment

Choose a reason for hiding this comment

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

Looks good, have a couple of comments.


Create a implementation instance of certprovisioner.
Create a implementation instance of certgenerator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Create an instance of CertGenerator ?

cp := SelfSignedCertProvisioner{
CommonName: "foo.bar.com"
}
cp := SelfSignedCertGenerator{}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: cp --> cg :)

cp := SelfSignedCertProvisioner{
CommonName: "foo.bar.com"
}
cp := SelfSignedCertGenerator{}

Provision the certificates.
Copy link
Contributor

Choose a reason for hiding this comment

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

Provision --> Generate

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package certprovisioner
package certgenerator
Copy link
Contributor

Choose a reason for hiding this comment

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

Want to throw it out there from caller's code readability perspective:

We can probably have a package name cert under admission

caller's code will look like

cg, err := cert.Generator() 
         
cw, err := cert.Writer()

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

@@ -24,8 +24,8 @@ type Certs struct {
CACert []byte
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Certs is giving an impression of multiple certificates and it is not.

some options.Cert or Certificate or CertArtifacts or CertContents

// CertWriter provides method to handle webhooks.
type CertWriter interface {
// Create a new CertWriter with the given runtime.Object
New(runtime.Object) (CertWriter, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure this method belongs in this interface ? its more like a constructor for CertWriter itself ?

// Create a new CertWriter with the given runtime.Object
New(runtime.Object) (CertWriter, error)
// Handle ensures that the webhooks it manages have the right certificates.
Handle() error
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be called WriteCert or EnsureCert or ManageCert or PopulateCert ?

}

// certio provides methods for handling certificates for webhook.
type certio interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

certReaderWriter is probably better name ?

if err != nil {
return err
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't appear to be thread-safe ?

Also, once cp.CertWriter is assigned and webhookConfiguration changes, cp.CertWriter won't get updated .. right..? wouldn't that be a problem ?

@mengqiy mengqiy force-pushed the webhook branch 2 times, most recently from 8d0492b to 2994c60 Compare June 19, 2018 00:57
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 19, 2018
@mengqiy

This comment has been minimized.

EnsureCert() error
}

func handleCommon(webhook *admissionregistrationv1beta1.Webhook, ch certReadWriter) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

document this function

var _ = BeforeSuite(func(done Done) {
logf.SetLogger(logf.ZapLogger(false))

testenv = &test.Environment{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we need to start the te if we are going to use it?

}

// New builds a new CertWriter for the provided webhook configuration.
func NewProvider(ops Options) (CertWriterProvider, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This writes to both locations? What does this do by default?

"k8s.io/apimachinery/pkg/runtime"
)

// MultiCertWriterProvider composes a slice of CertWriterProviders.
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a comment about what use cases this is good for.

@mengqiy
Copy link
Member Author

mengqiy commented Jun 21, 2018

PTAL

@mengqiy
Copy link
Member Author

mengqiy commented Jun 21, 2018

Coverage report:
sigs.k8s.io/controller-runtime/pkg/admission/cert/generator/selfsigned.go:27: ServiceToCommonName 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/generator/selfsigned.go:42: Generate 69.2%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:57: NewCertWriter 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:82: handleCommon 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:113: createIfNotExists 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:145: validCert 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:160: getWebhooksFromObject 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/certwriter.go:173: dnsNameForWebhook 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/multiple.go:32: EnsureCerts 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:53: EnsureCerts 95.5%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:98: parseAnnotations 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:109: ensureCert 80.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:135: write 78.6%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:158: overwrite 78.6%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:181: read 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:189: setOwnerRef 78.6%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:219: secretToCerts 100.0%
sigs.k8s.io/controller-runtime/pkg/admission/cert/writer/secret.go:230: certsToSecret 100.0%
total: (statements) 90.1%

Client: ops.Client,
CertGenerator: ops.CertGenerator,
}
//f := &FSCertWriter{
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this commented out?

Copy link
Member Author

Choose a reason for hiding this comment

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

It has not been implemented ans tested completely :)

}

// NewCertWriter builds a new CertWriter using the provided options.
// By default, it builds a MultiCertWriter that is composed of a SecretCertWriter and a FSCertWriter.
Copy link
Contributor

Choose a reason for hiding this comment

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

This document is not correct, it doesn't do the file writer

Copy link
Member Author

Choose a reason for hiding this comment

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

This will happen in one week.
I can remove it for now.


package writer

//import (
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you remove this file from the PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure

// Due to
// https://github.com/kubernetes/kubernetes/blob/5da925ad4fd070e687dc5255c177d5e7d542edd7/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/controller_ref.go#L35
isController := true
ownerRef := metav1.OwnerReference{
Copy link
Contributor

Choose a reason for hiding this comment

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

*generator.Artifacts, error) {
v := s.webhookMap[webhookName]

webhook := v.webhook
Copy link
Contributor

Choose a reason for hiding this comment

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

Most of this code is duplicated in write(). Please pull it out into a function.


func certsToSecret(certs *generator.Artifacts, sec apitypes.NamespacedName) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI: you shouldn't need to fill in the TypeMeta.

Copy link
Member Author

Choose a reason for hiding this comment

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

Why?
Does it mean the client.Client will set the TypeMeta fields for me if I pass it a *corev1.Secret?


import (
"reflect"
"sync"
Copy link
Contributor

Choose a reason for hiding this comment

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

cleanup these imports

return nil
}

var _ = Describe("MultipleCertWriterProvider", func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this has been renamed.

Provision the certificates using the CertWriter.

// writer can be either one of the CertWriters created above
err = writer.EnsureCerts(webhookConfiguration) // webhookConfiguration is an existing runtime.Object
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this get the certs out? Add an example of actually starting an http server.

ObjectMeta: metav1.ObjectMeta{
Name: "test-mwc",
Namespace: "test-ns",
UID: types.UID("123456"),
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can just use a string.

@pwittrock
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 21, 2018
@pwittrock
Copy link
Contributor

/approve

@pwittrock pwittrock added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 21, 2018
@k8s-ci-robot k8s-ci-robot merged commit 365c04b into kubernetes-sigs:master Jun 21, 2018
@mengqiy mengqiy deleted the webhook branch June 21, 2018 21:36
k8s-ci-robot added a commit that referenced this pull request Jun 22, 2018
address the remaining comments from #22
justinsb pushed a commit to justinsb/controller-runtime that referenced this pull request Dec 7, 2018
justinsb pushed a commit to justinsb/controller-runtime that referenced this pull request Dec 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants