mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 05:40:42 +00:00 
			
		
		
		
	implement kubectl procelain csr commands
This commit is contained in:
		| @@ -2884,6 +2884,44 @@ __EOF__ | |||||||
|   # Post-condition: valid-pod doesn't exist |   # Post-condition: valid-pod doesn't exist | ||||||
|   kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" '' |   kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" '' | ||||||
|  |  | ||||||
|  |   ################ | ||||||
|  |   # Certificates # | ||||||
|  |   ################ | ||||||
|  |  | ||||||
|  |   # approve | ||||||
|  |   kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' | ||||||
|  |   kubectl certificate approve foo "${kube_flags[@]}" | ||||||
|  |   kubectl get csr "${kube_flags[@]}" -o json | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' 'Approved' | ||||||
|  |   kubectl delete -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert csr "{{range.items}}{{$id_field}}{{end}}" '' | ||||||
|  |  | ||||||
|  |   kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' | ||||||
|  |   kubectl certificate approve -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kubectl get csr "${kube_flags[@]}" -o json | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' 'Approved' | ||||||
|  |   kubectl delete -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert csr "{{range.items}}{{$id_field}}{{end}}" '' | ||||||
|  |  | ||||||
|  |   # deny | ||||||
|  |   kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' | ||||||
|  |   kubectl certificate deny foo "${kube_flags[@]}" | ||||||
|  |   kubectl get csr "${kube_flags[@]}" -o json | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' 'Denied' | ||||||
|  |   kubectl delete -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert csr "{{range.items}}{{$id_field}}{{end}}" '' | ||||||
|  |  | ||||||
|  |   kubectl create -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' '' | ||||||
|  |   kubectl certificate deny -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kubectl get csr "${kube_flags[@]}" -o json | ||||||
|  |   kube::test::get_object_assert 'csr/foo' '{{range.status.conditions}}{{.type}}{{end}}' 'Denied' | ||||||
|  |   kubectl delete -f hack/testdata/csr.yml "${kube_flags[@]}" | ||||||
|  |   kube::test::get_object_assert csr "{{range.items}}{{$id_field}}{{end}}" '' | ||||||
|  |  | ||||||
|   kube::test::clear_all |   kube::test::clear_all | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								hack/testdata/csr.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								hack/testdata/csr.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | apiVersion: certificates.k8s.io/v1alpha1 | ||||||
|  | kind: CertificateSigningRequest | ||||||
|  | metadata: | ||||||
|  |   name: foo | ||||||
|  | spec: | ||||||
|  |   request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2d6Q0NBV3NDQVFBd0ZURVRNQkVHQTFVRUF4TUthM1ZpWlMxaFpHMXBiakNDQVNJd0RRWUpLb1pJaHZjTgpBUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTlJ5dFhkcWV6ZTFBdXFjZkpWYlFBY1BJejZWY2pXSTZ5WmlQa3lrCjAzUW9GaHJGRXhUQXNPTGVFUHlrQXc1YndUOWZiajRXMzZmR2k4RGxsd1FzVGoyYzVUTnBnQkkwbElDbzI4aGcKbHYvTDJsMnRsWUVKdDdTbVhjblNvaGJ5S0h4TERRUHVmTVBBTkZsaEFmTUdCWEhRcmZMajhrTk1MUDA4UlBsbAp0N3V4RDVRdFA0cHlGL1Nhbm1XVEtRNU56WlJ4TC82UmhJMEpxSHJmNFFjQmg2dlR5bnFaRGVmMWVxNjBnQXllClNPRkpKYWRuK3h2VEFqLzgxZk1TbjdOSlNnaktDYkNEeXQ1eS9UZHd0SzZnVUQzM01paE5uNXhKTVF0MUZXUVAKRzY3eTA1QVh6b0pqTm5sWVA1MnJsTlhvNzh6aVMrN1E4RklxQzY0c05vWWhxeGNDQXdFQUFhQXBNQ2NHQ1NxRwpTSWIzRFFFSkRqRWFNQmd3Q1FZRFZSMFRCQUl3QURBTEJnTlZIUThFQkFNQ0JlQXdEUVlKS29aSWh2Y05BUUVMCkJRQURnZ0VCQU5CazlwaHpWYUJBci9xZHN4bXdPR1NQa094UkZlR1lyemRvaW5LTzVGUGZER2JkU0VWQ0o1K0wKeWJTNUtmaUZYU1EvNmk0RE9WRWtxcnFrVElIc1JNSlJwbTZ5Zjk1TU4zSWVLak9jQlV2b2VWVlpxMUNOUU8zagp2dklmK1A1NStLdXpvK0NIT1F5RWlvTlRPaUtGWTJseStEZEEwMXMxbU9FMTZSWGlWeFhGcFhGeGRJVmRPK0oxClZ1MW5yWG5ZVFJQRmtyaG80MTlpaDQzNjRPcGZqYXFXVCtmd20ySVZQSlBoaUJpYi9RRzRhUGJJcFh3amlCUUMKemV6WlM2L01nQkt1bUdMZ3Z5MitXNU9UWTJ5ZFFMZFVxbERFNEU2MFhmdVZ6bk5zWjZDS0tYY1pVaW1ZTkkwNgpKa0t4bGRjd0V2cmI0SmN3M2RFQjdOOUwvSW9ZNXFBPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K | ||||||
| @@ -18,6 +18,7 @@ go_library( | |||||||
|         "apply.go", |         "apply.go", | ||||||
|         "attach.go", |         "attach.go", | ||||||
|         "autoscale.go", |         "autoscale.go", | ||||||
|  |         "certificates.go", | ||||||
|         "clusterinfo.go", |         "clusterinfo.go", | ||||||
|         "clusterinfo_dump.go", |         "clusterinfo_dump.go", | ||||||
|         "cmd.go", |         "cmd.go", | ||||||
| @@ -69,6 +70,7 @@ go_library( | |||||||
|         "//pkg/api/validation:go_default_library", |         "//pkg/api/validation:go_default_library", | ||||||
|         "//pkg/apimachinery/registered:go_default_library", |         "//pkg/apimachinery/registered:go_default_library", | ||||||
|         "//pkg/apis/batch/v1:go_default_library", |         "//pkg/apis/batch/v1:go_default_library", | ||||||
|  |         "//pkg/apis/certificates:go_default_library", | ||||||
|         "//pkg/apis/extensions/v1beta1:go_default_library", |         "//pkg/apis/extensions/v1beta1:go_default_library", | ||||||
|         "//pkg/client/clientset_generated/internalclientset:go_default_library", |         "//pkg/client/clientset_generated/internalclientset:go_default_library", | ||||||
|         "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", |         "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", | ||||||
|   | |||||||
							
								
								
									
										196
									
								
								pkg/kubectl/cmd/certificates.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								pkg/kubectl/cmd/certificates.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,196 @@ | |||||||
|  | /* | ||||||
|  | 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 cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  |  | ||||||
|  | 	"k8s.io/kubernetes/pkg/api/unversioned" | ||||||
|  | 	"k8s.io/kubernetes/pkg/apis/certificates" | ||||||
|  | 	"k8s.io/kubernetes/pkg/kubectl/cmd/templates" | ||||||
|  | 	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" | ||||||
|  | 	"k8s.io/kubernetes/pkg/kubectl/resource" | ||||||
|  |  | ||||||
|  | 	"github.com/spf13/cobra" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func NewCmdCertificate(f cmdutil.Factory, out io.Writer) *cobra.Command { | ||||||
|  | 	cmd := &cobra.Command{ | ||||||
|  | 		Use:   "certificate SUBCOMMAND", | ||||||
|  | 		Short: "Modify certificate resources.", | ||||||
|  | 		Run: func(cmd *cobra.Command, args []string) { | ||||||
|  | 			cmd.Help() | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cmd.AddCommand(NewCmdCertificateApprove(f, out)) | ||||||
|  | 	cmd.AddCommand(NewCmdCertificateDeny(f, out)) | ||||||
|  |  | ||||||
|  | 	return cmd | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type CertificateOptions struct { | ||||||
|  | 	resource.FilenameOptions | ||||||
|  | 	csrNames    []string | ||||||
|  | 	outputStyle string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (options *CertificateOptions) Complete(cmd *cobra.Command, args []string) error { | ||||||
|  | 	options.csrNames = args | ||||||
|  | 	options.outputStyle = cmdutil.GetFlagString(cmd, "output") | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (options *CertificateOptions) Validate() error { | ||||||
|  | 	if len(options.csrNames) < 1 && cmdutil.IsFilenameEmpty(options.Filenames) { | ||||||
|  | 		return fmt.Errorf("one or more CSRs must be specified as <name> or -f <filename>") | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewCmdCertificateApprove(f cmdutil.Factory, out io.Writer) *cobra.Command { | ||||||
|  | 	options := CertificateOptions{} | ||||||
|  | 	cmd := &cobra.Command{ | ||||||
|  | 		Use:   "approve (-f FILENAME | NAME)", | ||||||
|  | 		Short: "Approve a certificate signing request", | ||||||
|  | 		Long: templates.LongDesc(` | ||||||
|  | 		Approve a certificate signing request. | ||||||
|  |  | ||||||
|  | 		kubectl certificate approve allows a cluster admin to approve a certificate | ||||||
|  | 		signing request (CSR). This action tells a certificate signing controller to | ||||||
|  | 		issue a certificate to the requestor with the attributes requested in the CSR. | ||||||
|  |  | ||||||
|  | 		SECURITY NOTICE: Depending on the requested attributes, the issued certificate | ||||||
|  | 		can potentially grant a requester access to cluster resources or to authenticate | ||||||
|  | 		as a requested identity. Before approving a CSR, ensure you understand what the | ||||||
|  | 		signed certificate can do. | ||||||
|  | 		`), | ||||||
|  | 		Run: func(cmd *cobra.Command, args []string) { | ||||||
|  | 			cmdutil.CheckErr(options.Complete(cmd, args)) | ||||||
|  | 			cmdutil.CheckErr(options.Validate()) | ||||||
|  | 			cmdutil.CheckErr(options.RunCertificateApprove(f, out)) | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	cmdutil.AddOutputFlagsForMutation(cmd) | ||||||
|  | 	cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") | ||||||
|  |  | ||||||
|  | 	return cmd | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (options *CertificateOptions) RunCertificateApprove(f cmdutil.Factory, out io.Writer) error { | ||||||
|  | 	return options.modifyCertificateCondition(f, out, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string) { | ||||||
|  | 		var alreadyApproved bool | ||||||
|  | 		for _, c := range csr.Status.Conditions { | ||||||
|  | 			if c.Type == certificates.CertificateApproved { | ||||||
|  | 				alreadyApproved = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if alreadyApproved { | ||||||
|  | 			return csr, "approved" | ||||||
|  | 		} | ||||||
|  | 		csr.Status.Conditions = append(csr.Status.Conditions, certificates.CertificateSigningRequestCondition{ | ||||||
|  | 			Type:           certificates.CertificateApproved, | ||||||
|  | 			Reason:         "KubectlApprove", | ||||||
|  | 			Message:        "This CSR was approved by kubectl certificate approve.", | ||||||
|  | 			LastUpdateTime: unversioned.Now(), | ||||||
|  | 		}) | ||||||
|  | 		return csr, "approved" | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewCmdCertificateDeny(f cmdutil.Factory, out io.Writer) *cobra.Command { | ||||||
|  | 	options := CertificateOptions{} | ||||||
|  | 	cmd := &cobra.Command{ | ||||||
|  | 		Use:   "deny (-f FILENAME | NAME)", | ||||||
|  | 		Short: "Deny a certificate signing request", | ||||||
|  | 		Long: templates.LongDesc(` | ||||||
|  | 		Deny a certificate signing request. | ||||||
|  |  | ||||||
|  | 		kubectl certificate deny allows a cluster admin to deny a certificate | ||||||
|  | 		signing request (CSR). This action tells a certificate signing controller to | ||||||
|  | 		not to issue a certificate to the requestor. | ||||||
|  | 		`), | ||||||
|  | 		Run: func(cmd *cobra.Command, args []string) { | ||||||
|  | 			cmdutil.CheckErr(options.Complete(cmd, args)) | ||||||
|  | 			cmdutil.CheckErr(options.Validate()) | ||||||
|  | 			cmdutil.CheckErr(options.RunCertificateDeny(f, out)) | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	cmdutil.AddOutputFlagsForMutation(cmd) | ||||||
|  | 	cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update") | ||||||
|  |  | ||||||
|  | 	return cmd | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (options *CertificateOptions) RunCertificateDeny(f cmdutil.Factory, out io.Writer) error { | ||||||
|  | 	return options.modifyCertificateCondition(f, out, func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string) { | ||||||
|  | 		var alreadyDenied bool | ||||||
|  | 		for _, c := range csr.Status.Conditions { | ||||||
|  | 			if c.Type == certificates.CertificateDenied { | ||||||
|  | 				alreadyDenied = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if alreadyDenied { | ||||||
|  | 			return csr, "denied" | ||||||
|  | 		} | ||||||
|  | 		csr.Status.Conditions = append(csr.Status.Conditions, certificates.CertificateSigningRequestCondition{ | ||||||
|  | 			Type:           certificates.CertificateDenied, | ||||||
|  | 			Reason:         "KubectlDeny", | ||||||
|  | 			Message:        "This CSR was approved by kubectl certificate deny.", | ||||||
|  | 			LastUpdateTime: unversioned.Now(), | ||||||
|  | 		}) | ||||||
|  | 		return csr, "denied" | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (options *CertificateOptions) modifyCertificateCondition(f cmdutil.Factory, out io.Writer, modify func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, string)) error { | ||||||
|  | 	var found int | ||||||
|  | 	mapper, typer := f.Object() | ||||||
|  | 	c, err := f.ClientSet() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). | ||||||
|  | 		ContinueOnError(). | ||||||
|  | 		FilenameParam(false, &options.FilenameOptions). | ||||||
|  | 		ResourceNames("certificatesigningrequest", options.csrNames...). | ||||||
|  | 		RequireObject(true). | ||||||
|  | 		Flatten(). | ||||||
|  | 		Latest(). | ||||||
|  | 		Do() | ||||||
|  | 	err = r.Visit(func(info *resource.Info, err error) error { | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		csr := info.Object.(*certificates.CertificateSigningRequest) | ||||||
|  | 		csr, verb := modify(csr) | ||||||
|  | 		csr, err = c.Certificates(). | ||||||
|  | 			CertificateSigningRequests(). | ||||||
|  | 			UpdateApproval(csr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		found++ | ||||||
|  | 		cmdutil.PrintSuccess(mapper, options.outputStyle == "name", out, info.Mapping.Resource, info.Name, false, verb) | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 	if found == 0 { | ||||||
|  | 		fmt.Fprintf(out, "No resources found\n") | ||||||
|  | 	} | ||||||
|  | 	return err | ||||||
|  | } | ||||||
| @@ -251,6 +251,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob | |||||||
| 		{ | 		{ | ||||||
| 			Message: "Cluster Management Commands:", | 			Message: "Cluster Management Commands:", | ||||||
| 			Commands: []*cobra.Command{ | 			Commands: []*cobra.Command{ | ||||||
|  | 				NewCmdCertificate(f, out), | ||||||
| 				NewCmdClusterInfo(f, out), | 				NewCmdClusterInfo(f, out), | ||||||
| 				NewCmdTop(f, out, err), | 				NewCmdTop(f, out, err), | ||||||
| 				NewCmdCordon(f, out), | 				NewCmdCordon(f, out), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user