Merge pull request #58679 from CaoShuFeng/admission_webhook

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

support annotations for admission webhook

Depends on: https://github.com/kubernetes/kubernetes/pull/58143
**Release note**:
```release-note
Support annotations for remote admission webhooks.
```
This commit is contained in:
Kubernetes Submit Queue 2018-08-22 15:31:34 -07:00 committed by GitHub
commit 4e76bb487e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 380 additions and 79 deletions

View File

@ -92,6 +92,12 @@ type AdmissionResponse struct {
// PatchType indicates the form the Patch will take. Currently we only support "JSONPatch".
// +optional
PatchType *PatchType
// AuditAnnotations is an unstructured key value map set by remote admission controller (e.g. error=image-blacklisted).
// MutatingAdmissionWebhook and ValidatingAdmissionWebhook admission controller will prefix the keys with
// admission webhook name (e.g. imagepolicy.example.com/error=image-blacklisted). AuditAnnotations will be provided by
// the admission webhook to add additional context to the audit log for this request.
// +optional
AuditAnnotations map[string]string
}
// PatchType is the type of patch being used to represent the mutated object

View File

@ -129,6 +129,7 @@ func autoConvert_v1beta1_AdmissionResponse_To_admission_AdmissionResponse(in *v1
out.Result = (*v1.Status)(unsafe.Pointer(in.Result))
out.Patch = *(*[]byte)(unsafe.Pointer(&in.Patch))
out.PatchType = (*admission.PatchType)(unsafe.Pointer(in.PatchType))
out.AuditAnnotations = *(*map[string]string)(unsafe.Pointer(&in.AuditAnnotations))
return nil
}
@ -143,6 +144,7 @@ func autoConvert_admission_AdmissionResponse_To_v1beta1_AdmissionResponse(in *ad
out.Result = (*v1.Status)(unsafe.Pointer(in.Result))
out.Patch = *(*[]byte)(unsafe.Pointer(&in.Patch))
out.PatchType = (*v1beta1.PatchType)(unsafe.Pointer(in.PatchType))
out.AuditAnnotations = *(*map[string]string)(unsafe.Pointer(&in.AuditAnnotations))
return nil
}

View File

@ -68,6 +68,13 @@ func (in *AdmissionResponse) DeepCopyInto(out *AdmissionResponse) {
*out = new(PatchType)
**out = **in
}
if in.AuditAnnotations != nil {
in, out := &in.AuditAnnotations, &out.AuditAnnotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}

View File

@ -20,6 +20,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
],
)

View File

@ -39,6 +39,8 @@ import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v
import k8s_io_apimachinery_pkg_types "k8s.io/apimachinery/pkg/types"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
import strings "strings"
import reflect "reflect"
@ -199,6 +201,28 @@ func (m *AdmissionResponse) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PatchType)))
i += copy(dAtA[i:], *m.PatchType)
}
if len(m.AuditAnnotations) > 0 {
keysForAuditAnnotations := make([]string, 0, len(m.AuditAnnotations))
for k := range m.AuditAnnotations {
keysForAuditAnnotations = append(keysForAuditAnnotations, string(k))
}
github_com_gogo_protobuf_sortkeys.Strings(keysForAuditAnnotations)
for _, k := range keysForAuditAnnotations {
dAtA[i] = 0x32
i++
v := m.AuditAnnotations[string(k)]
mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
i = encodeVarintGenerated(dAtA, i, uint64(mapSize))
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(k)))
i += copy(dAtA[i:], k)
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(v)))
i += copy(dAtA[i:], v)
}
}
return i, nil
}
@ -311,6 +335,14 @@ func (m *AdmissionResponse) Size() (n int) {
l = len(*m.PatchType)
n += 1 + l + sovGenerated(uint64(l))
}
if len(m.AuditAnnotations) > 0 {
for k, v := range m.AuditAnnotations {
_ = k
_ = v
mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize))
}
}
return n
}
@ -364,12 +396,23 @@ func (this *AdmissionResponse) String() string {
if this == nil {
return "nil"
}
keysForAuditAnnotations := make([]string, 0, len(this.AuditAnnotations))
for k := range this.AuditAnnotations {
keysForAuditAnnotations = append(keysForAuditAnnotations, k)
}
github_com_gogo_protobuf_sortkeys.Strings(keysForAuditAnnotations)
mapStringForAuditAnnotations := "map[string]string{"
for _, k := range keysForAuditAnnotations {
mapStringForAuditAnnotations += fmt.Sprintf("%v: %v,", k, this.AuditAnnotations[k])
}
mapStringForAuditAnnotations += "}"
s := strings.Join([]string{`&AdmissionResponse{`,
`UID:` + fmt.Sprintf("%v", this.UID) + `,`,
`Allowed:` + fmt.Sprintf("%v", this.Allowed) + `,`,
`Result:` + strings.Replace(fmt.Sprintf("%v", this.Result), "Status", "k8s_io_apimachinery_pkg_apis_meta_v1.Status", 1) + `,`,
`Patch:` + valueToStringGenerated(this.Patch) + `,`,
`PatchType:` + valueToStringGenerated(this.PatchType) + `,`,
`AuditAnnotations:` + mapStringForAuditAnnotations + `,`,
`}`,
}, "")
return s
@ -910,6 +953,122 @@ func (m *AdmissionResponse) Unmarshal(dAtA []byte) error {
s := PatchType(dAtA[iNdEx:postIndex])
m.PatchType = &s
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AuditAnnotations", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.AuditAnnotations == nil {
m.AuditAnnotations = make(map[string]string)
}
if iNdEx < postIndex {
var valuekey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthGenerated
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
return io.ErrUnexpectedEOF
}
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
m.AuditAnnotations[mapkey] = mapvalue
} else {
var mapvalue string
m.AuditAnnotations[mapkey] = mapvalue
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@ -1157,51 +1316,55 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 728 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xdb, 0x48,
0x14, 0x8f, 0x21, 0xff, 0x3c, 0x41, 0x0b, 0xcc, 0x5e, 0xac, 0x68, 0xe5, 0xb0, 0x1c, 0x56, 0xac,
0x04, 0xe3, 0x05, 0xed, 0x22, 0xb4, 0xda, 0x0b, 0x16, 0x68, 0x85, 0x56, 0x02, 0x34, 0x90, 0x55,
0xdb, 0x43, 0xa5, 0x89, 0xf3, 0x48, 0xdc, 0xc4, 0x1e, 0xd7, 0x33, 0x0e, 0xe5, 0xd6, 0x8f, 0xd0,
0x6f, 0xd2, 0x0f, 0xd1, 0x0b, 0x47, 0x8e, 0x9c, 0xa2, 0x92, 0x7e, 0x80, 0xde, 0x39, 0x55, 0x1e,
0x8f, 0xe3, 0x94, 0x96, 0x96, 0x56, 0x3d, 0x65, 0xde, 0x7b, 0xbf, 0xdf, 0xef, 0xc5, 0xbf, 0xf7,
0x66, 0xd0, 0xfe, 0x60, 0x47, 0x10, 0x9f, 0x3b, 0x83, 0xa4, 0x03, 0x71, 0x08, 0x12, 0x84, 0x33,
0x82, 0xb0, 0xcb, 0x63, 0x47, 0x17, 0x58, 0xe4, 0x3b, 0xac, 0x1b, 0xf8, 0x42, 0xf8, 0x3c, 0x74,
0x46, 0x9b, 0x1d, 0x90, 0x6c, 0xd3, 0xe9, 0x41, 0x08, 0x31, 0x93, 0xd0, 0x25, 0x51, 0xcc, 0x25,
0xc7, 0xbf, 0x64, 0x68, 0xc2, 0x22, 0x9f, 0x4c, 0xd1, 0x44, 0xa3, 0x9b, 0x1b, 0x3d, 0x5f, 0xf6,
0x93, 0x0e, 0xf1, 0x78, 0xe0, 0xf4, 0x78, 0x8f, 0x3b, 0x8a, 0xd4, 0x49, 0xce, 0x54, 0xa4, 0x02,
0x75, 0xca, 0xc4, 0x9a, 0xeb, 0xb3, 0xad, 0x13, 0xd9, 0x87, 0x50, 0xfa, 0x1e, 0x93, 0x59, 0xff,
0xbb, 0xad, 0x9b, 0x7f, 0x16, 0xe8, 0x80, 0x79, 0x7d, 0x3f, 0x84, 0xf8, 0xc2, 0x89, 0x06, 0xbd,
0x34, 0x21, 0x9c, 0x00, 0x24, 0xfb, 0x1c, 0xcb, 0xb9, 0x8f, 0x15, 0x27, 0xa1, 0xf4, 0x03, 0xf8,
0x84, 0xb0, 0xfd, 0x35, 0x82, 0xf0, 0xfa, 0x10, 0xb0, 0xbb, 0xbc, 0xd5, 0xf7, 0x15, 0xb4, 0xb4,
0x9b, 0x3b, 0x42, 0xe1, 0x79, 0x02, 0x42, 0x62, 0x17, 0xcd, 0x27, 0x7e, 0xd7, 0x32, 0x56, 0x8c,
0x35, 0xd3, 0xfd, 0xe3, 0x72, 0xdc, 0x2a, 0x4d, 0xc6, 0xad, 0xf9, 0xf6, 0xc1, 0xde, 0xed, 0xb8,
0xf5, 0xeb, 0x7d, 0x8d, 0xe4, 0x45, 0x04, 0x82, 0xb4, 0x0f, 0xf6, 0x68, 0x4a, 0xc6, 0x8f, 0x50,
0x79, 0xe0, 0x87, 0x5d, 0x6b, 0x6e, 0xc5, 0x58, 0x6b, 0x6c, 0x6d, 0x93, 0x62, 0x02, 0x53, 0x1a,
0x89, 0x06, 0xbd, 0x34, 0x21, 0x48, 0x6a, 0x03, 0x19, 0x6d, 0x92, 0x7f, 0x63, 0x9e, 0x44, 0xff,
0x43, 0x9c, 0xfe, 0x99, 0xff, 0xfc, 0xb0, 0xeb, 0x2e, 0xe8, 0xe6, 0xe5, 0x34, 0xa2, 0x4a, 0x11,
0xf7, 0x51, 0x3d, 0x06, 0xc1, 0x93, 0xd8, 0x03, 0x6b, 0x5e, 0xa9, 0xff, 0xfd, 0xed, 0xea, 0x54,
0x2b, 0xb8, 0x4b, 0xba, 0x43, 0x3d, 0xcf, 0xd0, 0xa9, 0x3a, 0xfe, 0x0b, 0x35, 0x44, 0xd2, 0xc9,
0x0b, 0x56, 0x59, 0xf9, 0xf1, 0xb3, 0x26, 0x34, 0x4e, 0x8a, 0x12, 0x9d, 0xc5, 0xe1, 0x15, 0x54,
0x0e, 0x59, 0x00, 0x56, 0x45, 0xe1, 0xa7, 0x9f, 0x70, 0xc8, 0x02, 0xa0, 0xaa, 0x82, 0x1d, 0x64,
0xa6, 0xbf, 0x22, 0x62, 0x1e, 0x58, 0x55, 0x05, 0x5b, 0xd6, 0x30, 0xf3, 0x30, 0x2f, 0xd0, 0x02,
0x83, 0xff, 0x41, 0x26, 0x8f, 0xd2, 0xc1, 0xf9, 0x3c, 0xb4, 0x6a, 0x8a, 0x60, 0xe7, 0x84, 0xa3,
0xbc, 0x70, 0x3b, 0x1b, 0xd0, 0x82, 0x80, 0x4f, 0x51, 0x3d, 0x11, 0x10, 0x1f, 0x84, 0x67, 0xdc,
0xaa, 0x2b, 0xc7, 0x7e, 0x23, 0xb3, 0x37, 0xe2, 0xa3, 0x25, 0x4e, 0x9d, 0x6a, 0x6b, 0x74, 0xe1,
0x4e, 0x9e, 0xa1, 0x53, 0x25, 0xdc, 0x46, 0x55, 0xde, 0x79, 0x06, 0x9e, 0xb4, 0x4c, 0xa5, 0xb9,
0x71, 0xef, 0x14, 0xf4, 0x0e, 0x12, 0xca, 0xce, 0xf7, 0x5f, 0x48, 0x08, 0xd3, 0x01, 0xb8, 0x3f,
0x69, 0xe9, 0xea, 0x91, 0x12, 0xa1, 0x5a, 0x0c, 0x3f, 0x45, 0x26, 0x1f, 0x76, 0xb3, 0xa4, 0x85,
0xbe, 0x47, 0x79, 0x6a, 0xe5, 0x51, 0xae, 0x43, 0x0b, 0xc9, 0xd5, 0xd7, 0x73, 0x68, 0x79, 0x66,
0xe3, 0x45, 0xc4, 0x43, 0x01, 0x3f, 0x64, 0xe5, 0x7f, 0x47, 0x35, 0x36, 0x1c, 0xf2, 0x73, 0xc8,
0xb6, 0xbe, 0xee, 0x2e, 0x6a, 0x9d, 0xda, 0x6e, 0x96, 0xa6, 0x79, 0x1d, 0x1f, 0xa3, 0xaa, 0x90,
0x4c, 0x26, 0x42, 0x6f, 0xf0, 0xfa, 0xc3, 0x36, 0xf8, 0x44, 0x71, 0x5c, 0x94, 0xda, 0x46, 0x41,
0x24, 0x43, 0x49, 0xb5, 0x0e, 0x6e, 0xa1, 0x4a, 0xc4, 0xa4, 0xd7, 0x57, 0x5b, 0xba, 0xe0, 0x9a,
0x93, 0x71, 0xab, 0x72, 0x9c, 0x26, 0x68, 0x96, 0xc7, 0x3b, 0xc8, 0x54, 0x87, 0xd3, 0x8b, 0x28,
0x5f, 0xcd, 0x66, 0x6a, 0xd2, 0x71, 0x9e, 0xbc, 0x9d, 0x0d, 0x68, 0x01, 0x5e, 0x7d, 0x63, 0xa0,
0xc5, 0x19, 0xc7, 0x46, 0x3e, 0x9c, 0xe3, 0x36, 0xaa, 0xc5, 0xd9, 0x6b, 0xa1, 0x3c, 0x6b, 0x6c,
0x11, 0xf2, 0xa5, 0x37, 0x96, 0xdc, 0x7d, 0x63, 0xdc, 0x46, 0xea, 0x8b, 0x0e, 0x68, 0xae, 0x85,
0x1f, 0xab, 0xbb, 0xad, 0x46, 0xa2, 0x5f, 0x0e, 0xe7, 0xc1, 0xba, 0x19, 0xcd, 0x5d, 0xd0, 0x97,
0x59, 0x45, 0x74, 0x2a, 0xe7, 0x6e, 0x5c, 0xde, 0xd8, 0xa5, 0xab, 0x1b, 0xbb, 0x74, 0x7d, 0x63,
0x97, 0x5e, 0x4e, 0x6c, 0xe3, 0x72, 0x62, 0x1b, 0x57, 0x13, 0xdb, 0xb8, 0x9e, 0xd8, 0xc6, 0xdb,
0x89, 0x6d, 0xbc, 0x7a, 0x67, 0x97, 0x9e, 0xd4, 0xb4, 0xf0, 0x87, 0x00, 0x00, 0x00, 0xff, 0xff,
0xb6, 0xe9, 0xbc, 0x6f, 0x7a, 0x06, 0x00, 0x00,
// 800 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0xe3, 0x44,
0x14, 0x8e, 0x37, 0x3f, 0x3d, 0xa9, 0xd8, 0xec, 0x00, 0x92, 0x15, 0x21, 0x27, 0xf4, 0x80, 0x8a,
0xb4, 0x1d, 0xd3, 0x0a, 0x56, 0xd5, 0x8a, 0x4b, 0xcc, 0x46, 0xa8, 0x42, 0x6a, 0xab, 0x69, 0x83,
0x80, 0x03, 0xd2, 0xc4, 0x9e, 0x26, 0x26, 0xf1, 0x8c, 0xf1, 0x8c, 0x53, 0x72, 0x43, 0x5c, 0xb9,
0xf0, 0x3f, 0x71, 0xe9, 0xb1, 0xc7, 0x9e, 0x22, 0x1a, 0xfe, 0x00, 0xee, 0x3d, 0x21, 0x8f, 0xc7,
0x71, 0x48, 0x5b, 0x68, 0xd1, 0x9e, 0x32, 0xef, 0xbd, 0xef, 0xfb, 0x9e, 0xe7, 0x7b, 0x2f, 0x03,
0xfa, 0x93, 0x03, 0x81, 0x02, 0xee, 0x4c, 0x92, 0x21, 0x8d, 0x19, 0x95, 0x54, 0x38, 0x33, 0xca,
0x7c, 0x1e, 0x3b, 0xba, 0x40, 0xa2, 0xc0, 0x21, 0x7e, 0x18, 0x08, 0x11, 0x70, 0xe6, 0xcc, 0xf6,
0x86, 0x54, 0x92, 0x3d, 0x67, 0x44, 0x19, 0x8d, 0x89, 0xa4, 0x3e, 0x8a, 0x62, 0x2e, 0x39, 0xfc,
0x20, 0x43, 0x23, 0x12, 0x05, 0x68, 0x85, 0x46, 0x1a, 0xdd, 0xde, 0x1d, 0x05, 0x72, 0x9c, 0x0c,
0x91, 0xc7, 0x43, 0x67, 0xc4, 0x47, 0xdc, 0x51, 0xa4, 0x61, 0x72, 0xae, 0x22, 0x15, 0xa8, 0x53,
0x26, 0xd6, 0x7e, 0xb9, 0xde, 0x3a, 0x91, 0x63, 0xca, 0x64, 0xe0, 0x11, 0x99, 0xf5, 0xdf, 0x6c,
0xdd, 0xfe, 0xb4, 0x40, 0x87, 0xc4, 0x1b, 0x07, 0x8c, 0xc6, 0x73, 0x27, 0x9a, 0x8c, 0xd2, 0x84,
0x70, 0x42, 0x2a, 0xc9, 0x7d, 0x2c, 0xe7, 0x21, 0x56, 0x9c, 0x30, 0x19, 0x84, 0xf4, 0x0e, 0xe1,
0xd5, 0x7f, 0x11, 0x84, 0x37, 0xa6, 0x21, 0xd9, 0xe4, 0x6d, 0xff, 0x55, 0x05, 0xad, 0x5e, 0xee,
0x08, 0xa6, 0x3f, 0x26, 0x54, 0x48, 0xe8, 0x82, 0x72, 0x12, 0xf8, 0x96, 0xd1, 0x35, 0x76, 0x4c,
0xf7, 0x93, 0xcb, 0x45, 0xa7, 0xb4, 0x5c, 0x74, 0xca, 0x83, 0xc3, 0x37, 0xb7, 0x8b, 0xce, 0x87,
0x0f, 0x35, 0x92, 0xf3, 0x88, 0x0a, 0x34, 0x38, 0x7c, 0x83, 0x53, 0x32, 0xfc, 0x06, 0x54, 0x26,
0x01, 0xf3, 0xad, 0x67, 0x5d, 0x63, 0xa7, 0xb9, 0xff, 0x0a, 0x15, 0x13, 0x58, 0xd1, 0x50, 0x34,
0x19, 0xa5, 0x09, 0x81, 0x52, 0x1b, 0xd0, 0x6c, 0x0f, 0x7d, 0x19, 0xf3, 0x24, 0xfa, 0x9a, 0xc6,
0xe9, 0xc7, 0x7c, 0x15, 0x30, 0xdf, 0xdd, 0xd2, 0xcd, 0x2b, 0x69, 0x84, 0x95, 0x22, 0x1c, 0x83,
0x46, 0x4c, 0x05, 0x4f, 0x62, 0x8f, 0x5a, 0x65, 0xa5, 0xfe, 0xfa, 0xe9, 0xea, 0x58, 0x2b, 0xb8,
0x2d, 0xdd, 0xa1, 0x91, 0x67, 0xf0, 0x4a, 0x1d, 0x7e, 0x06, 0x9a, 0x22, 0x19, 0xe6, 0x05, 0xab,
0xa2, 0xfc, 0x78, 0x57, 0x13, 0x9a, 0xa7, 0x45, 0x09, 0xaf, 0xe3, 0x60, 0x17, 0x54, 0x18, 0x09,
0xa9, 0x55, 0x55, 0xf8, 0xd5, 0x15, 0x8e, 0x48, 0x48, 0xb1, 0xaa, 0x40, 0x07, 0x98, 0xe9, 0xaf,
0x88, 0x88, 0x47, 0xad, 0x9a, 0x82, 0xbd, 0xd0, 0x30, 0xf3, 0x28, 0x2f, 0xe0, 0x02, 0x03, 0x3f,
0x07, 0x26, 0x8f, 0xd2, 0xc1, 0x05, 0x9c, 0x59, 0x75, 0x45, 0xb0, 0x73, 0xc2, 0x71, 0x5e, 0xb8,
0x5d, 0x0f, 0x70, 0x41, 0x80, 0x67, 0xa0, 0x91, 0x08, 0x1a, 0x1f, 0xb2, 0x73, 0x6e, 0x35, 0x94,
0x63, 0x1f, 0xa1, 0xf5, 0x7f, 0xc4, 0x3f, 0x96, 0x38, 0x75, 0x6a, 0xa0, 0xd1, 0x85, 0x3b, 0x79,
0x06, 0xaf, 0x94, 0xe0, 0x00, 0xd4, 0xf8, 0xf0, 0x07, 0xea, 0x49, 0xcb, 0x54, 0x9a, 0xbb, 0x0f,
0x4e, 0x41, 0xef, 0x20, 0xc2, 0xe4, 0xa2, 0xff, 0x93, 0xa4, 0x2c, 0x1d, 0x80, 0xfb, 0x8e, 0x96,
0xae, 0x1d, 0x2b, 0x11, 0xac, 0xc5, 0xe0, 0xf7, 0xc0, 0xe4, 0x53, 0x3f, 0x4b, 0x5a, 0xe0, 0xff,
0x28, 0xaf, 0xac, 0x3c, 0xce, 0x75, 0x70, 0x21, 0xb9, 0xfd, 0x4b, 0x05, 0xbc, 0x58, 0xdb, 0x78,
0x11, 0x71, 0x26, 0xe8, 0x5b, 0x59, 0xf9, 0x8f, 0x41, 0x9d, 0x4c, 0xa7, 0xfc, 0x82, 0x66, 0x5b,
0xdf, 0x70, 0x9f, 0x6b, 0x9d, 0x7a, 0x2f, 0x4b, 0xe3, 0xbc, 0x0e, 0x4f, 0x40, 0x4d, 0x48, 0x22,
0x13, 0xa1, 0x37, 0xf8, 0xe5, 0xe3, 0x36, 0xf8, 0x54, 0x71, 0x5c, 0x90, 0xda, 0x86, 0xa9, 0x48,
0xa6, 0x12, 0x6b, 0x1d, 0xd8, 0x01, 0xd5, 0x88, 0x48, 0x6f, 0xac, 0xb6, 0x74, 0xcb, 0x35, 0x97,
0x8b, 0x4e, 0xf5, 0x24, 0x4d, 0xe0, 0x2c, 0x0f, 0x0f, 0x80, 0xa9, 0x0e, 0x67, 0xf3, 0x28, 0x5f,
0xcd, 0x76, 0x6a, 0xd2, 0x49, 0x9e, 0xbc, 0x5d, 0x0f, 0x70, 0x01, 0x86, 0xbf, 0x1a, 0xa0, 0x45,
0x12, 0x3f, 0x90, 0x3d, 0xc6, 0xb8, 0x54, 0x4b, 0x22, 0xac, 0x5a, 0xb7, 0xbc, 0xd3, 0xdc, 0xef,
0xa3, 0x7f, 0x7b, 0x59, 0xd1, 0x1d, 0x9f, 0x51, 0x6f, 0x43, 0xa7, 0xcf, 0x64, 0x3c, 0x77, 0x2d,
0x6d, 0x54, 0x6b, 0xb3, 0x8c, 0xef, 0x34, 0x6e, 0x7f, 0x01, 0xde, 0xbf, 0x57, 0x04, 0xb6, 0x40,
0x79, 0x42, 0xe7, 0xd9, 0x08, 0x71, 0x7a, 0x84, 0xef, 0x81, 0xea, 0x8c, 0x4c, 0x13, 0xaa, 0xc6,
0x61, 0xe2, 0x2c, 0x78, 0xfd, 0xec, 0xc0, 0xd8, 0xfe, 0xdd, 0x00, 0xcf, 0xd7, 0x3e, 0x6e, 0x16,
0xd0, 0x0b, 0x38, 0x00, 0xf5, 0x38, 0x7b, 0x00, 0x95, 0x46, 0x73, 0x1f, 0x3d, 0xfa, 0x72, 0x8a,
0xe5, 0x36, 0xd3, 0x51, 0xeb, 0x00, 0xe7, 0x5a, 0xf0, 0x5b, 0xf5, 0x5c, 0xa9, 0xdb, 0xeb, 0xc7,
0xd0, 0x79, 0xa2, 0x69, 0xee, 0x96, 0x7e, 0x9f, 0x54, 0x84, 0x57, 0x72, 0xee, 0xee, 0xe5, 0x8d,
0x5d, 0xba, 0xba, 0xb1, 0x4b, 0xd7, 0x37, 0x76, 0xe9, 0xe7, 0xa5, 0x6d, 0x5c, 0x2e, 0x6d, 0xe3,
0x6a, 0x69, 0x1b, 0xd7, 0x4b, 0xdb, 0xf8, 0x63, 0x69, 0x1b, 0xbf, 0xfd, 0x69, 0x97, 0xbe, 0xab,
0x6b, 0xe1, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x8d, 0xe4, 0x17, 0xc7, 0x4d, 0x07, 0x00, 0x00,
}

View File

@ -96,6 +96,13 @@ message AdmissionResponse {
// The type of Patch. Currently we only allow "JSONPatch".
// +optional
optional string patchType = 5;
// AuditAnnotations is an unstructured key value map set by remote admission controller (e.g. error=image-blacklisted).
// MutatingAdmissionWebhook and ValidatingAdmissionWebhook admission controller will prefix the keys with
// admission webhook name (e.g. imagepolicy.example.com/error=image-blacklisted). AuditAnnotations will be provided by
// the admission webhook to add additional context to the audit log for this request.
// +optional
map<string, string> auditAnnotations = 6;
}
// AdmissionReview describes an admission review request/response.

View File

@ -94,6 +94,13 @@ type AdmissionResponse struct {
// The type of Patch. Currently we only allow "JSONPatch".
// +optional
PatchType *PatchType `json:"patchType,omitempty" protobuf:"bytes,5,opt,name=patchType"`
// AuditAnnotations is an unstructured key value map set by remote admission controller (e.g. error=image-blacklisted).
// MutatingAdmissionWebhook and ValidatingAdmissionWebhook admission controller will prefix the keys with
// admission webhook name (e.g. imagepolicy.example.com/error=image-blacklisted). AuditAnnotations will be provided by
// the admission webhook to add additional context to the audit log for this request.
// +optional
AuditAnnotations map[string]string `json:"auditAnnotations,omitempty" protobuf:"bytes,6,opt,name=auditAnnotations"`
}
// PatchType is the type of patch being used to represent the mutated object

View File

@ -52,6 +52,7 @@ var map_AdmissionResponse = map[string]string{
"status": "Result contains extra details into why an admission request was denied. This field IS NOT consulted in any way if \"Allowed\" is \"true\".",
"patch": "The patch body. Currently we only support \"JSONPatch\" which implements RFC 6902.",
"patchType": "The type of Patch. Currently we only allow \"JSONPatch\".",
"auditAnnotations": "AuditAnnotations is an unstructured key value map set by remote admission controller (e.g. error=image-blacklisted). MutatingAdmissionWebhook and ValidatingAdmissionWebhook admission controller will prefix the keys with admission webhook name (e.g. imagepolicy.example.com/error=image-blacklisted). AuditAnnotations will be provided by the admission webhook to add additional context to the audit log for this request.",
}
func (AdmissionResponse) SwaggerDoc() map[string]string {

View File

@ -64,6 +64,13 @@ func (in *AdmissionResponse) DeepCopyInto(out *AdmissionResponse) {
*out = new(PatchType)
**out = **in
}
if in.AuditAnnotations != nil {
in, out := &in.AuditAnnotations, &out.AuditAnnotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}

View File

@ -51,6 +51,7 @@ go_test(
"//staging/src/k8s.io/apiserver/pkg/apis/example:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example2/v1:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
],
)

View File

@ -102,6 +102,13 @@ func (a *mutatingDispatcher) callAttrMutatingHook(ctx context.Context, h *v1beta
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
}
for k, v := range response.Response.AuditAnnotations {
key := h.Name + "/" + k
if err := attr.AddAnnotation(key, v); err != nil {
glog.Warningf("Failed to set admission audit annotation %s to %s for mutating webhook %s: %v", key, v, h.Name, err)
}
}
if !response.Response.Allowed {
return webhookerrors.ToStatusErr(h.Name, response.Response.Result)
}

View File

@ -22,6 +22,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/api/admission/v1beta1"
@ -102,6 +103,16 @@ func TestAdmit(t *testing.T) {
if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr {
t.Errorf("%s: expected a StatusError, got %T", tt.Name, err)
}
fakeAttr, ok := attr.(*webhooktesting.FakeAttributes)
if !ok {
t.Errorf("Unexpected error, failed to convert attr to webhooktesting.FakeAttributes")
continue
}
if len(tt.ExpectAnnotations) == 0 {
assert.Empty(t, fakeAttr.GetAnnotations(), tt.Name+": annotations not set as expected.")
} else {
assert.Equal(t, tt.ExpectAnnotations, fakeAttr.GetAnnotations(), tt.Name+": annotations not set as expected.")
}
}
}

View File

@ -18,6 +18,7 @@ package testing
import (
"net/url"
"sync"
registrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
corev1 "k8s.io/api/core/v1"
@ -95,7 +96,37 @@ func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind sch
UID: "webhook-test",
}
return admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, dryRun, &userInfo)
return &FakeAttributes{
Attributes: admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, dryRun, &userInfo),
}
}
// FakeAttributes decorate admission.Attributes. It's used to trace the added annotations.
type FakeAttributes struct {
admission.Attributes
annotations map[string]string
mutex sync.Mutex
}
// AddAnnotation adds an annotation key value pair to FakeAttributes
func (f *FakeAttributes) AddAnnotation(k, v string) error {
f.mutex.Lock()
defer f.mutex.Unlock()
if err := f.Attributes.AddAnnotation(k, v); err != nil {
return err
}
if f.annotations == nil {
f.annotations = make(map[string]string)
}
f.annotations[k] = v
return nil
}
// GetAnnotations reads annotations from FakeAttributes
func (f *FakeAttributes) GetAnnotations() map[string]string {
f.mutex.Lock()
defer f.mutex.Unlock()
return f.annotations
}
// NewAttribute returns static admission Attributes for testing.
@ -154,6 +185,7 @@ type Test struct {
ExpectLabels map[string]string
ExpectAllow bool
ErrorContains string
ExpectAnnotations map[string]string
}
// NewNonMutatingTestCases returns test cases with a given base url.
@ -181,12 +213,13 @@ func NewNonMutatingTestCases(url *url.URL) []Test {
{
Name: "match & allow",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
Name: "allow.example.com",
ClientConfig: ccfgSVC("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
}},
ExpectAllow: true,
ExpectAnnotations: map[string]string{"allow.example.com/key1": "value1"},
},
{
Name: "match & disallow",
@ -312,12 +345,13 @@ func NewNonMutatingTestCases(url *url.URL) []Test {
{
Name: "match & allow (url)",
Webhooks: []registrationv1beta1.Webhook{{
Name: "allow",
Name: "allow.example.com",
ClientConfig: ccfgURL("allow"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
}},
ExpectAllow: true,
ExpectAnnotations: map[string]string{"allow.example.com/key1": "value1"},
},
{
Name: "match & disallow (url)",
@ -374,6 +408,16 @@ func NewNonMutatingTestCases(url *url.URL) []Test {
IsDryRun: true,
ErrorContains: "does not support dry run",
},
{
Name: "illegal annotation format",
Webhooks: []registrationv1beta1.Webhook{{
Name: "invalidAnnotation",
ClientConfig: ccfgURL("invalidAnnotation"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
}},
ExpectAllow: true,
},
// No need to test everything with the url case, since only the
// connection is different.
}
@ -387,7 +431,7 @@ func NewMutatingTestCases(url *url.URL) []Test {
{
Name: "match & remove label",
Webhooks: []registrationv1beta1.Webhook{{
Name: "removeLabel",
Name: "removelabel.example.com",
ClientConfig: ccfgSVC("removeLabel"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
@ -395,6 +439,7 @@ func NewMutatingTestCases(url *url.URL) []Test {
ExpectAllow: true,
AdditionalLabels: map[string]string{"remove": "me"},
ExpectLabels: map[string]string{"pod.name": "my-pod"},
ExpectAnnotations: map[string]string{"removelabel.example.com/key1": "value1"},
},
{
Name: "match & add label",
@ -422,7 +467,7 @@ func NewMutatingTestCases(url *url.URL) []Test {
{
Name: "match CRD & remove label",
Webhooks: []registrationv1beta1.Webhook{{
Name: "removeLabel",
Name: "removelabel.example.com",
ClientConfig: ccfgSVC("removeLabel"),
Rules: matchEverythingRules,
NamespaceSelector: &metav1.LabelSelector{},
@ -431,6 +476,7 @@ func NewMutatingTestCases(url *url.URL) []Test {
ExpectAllow: true,
AdditionalLabels: map[string]string{"remove": "me"},
ExpectLabels: map[string]string{"crd.name": "my-test-crd"},
ExpectAnnotations: map[string]string{"removelabel.example.com/key1": "value1"},
},
{
Name: "match & invalid mutation",

View File

@ -83,6 +83,9 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{
Response: &v1beta1.AdmissionResponse{
Allowed: true,
AuditAnnotations: map[string]string{
"key1": "value1",
},
},
})
case "/removeLabel":
@ -93,6 +96,9 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) {
Allowed: true,
PatchType: &pt,
Patch: []byte(`[{"op": "remove", "path": "/metadata/labels/remove"}]`),
AuditAnnotations: map[string]string{
"key1": "value1",
},
},
})
case "/addLabel":
@ -118,6 +124,16 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) {
case "/nilResponse":
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{})
case "/invalidAnnotation":
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(&v1beta1.AdmissionReview{
Response: &v1beta1.AdmissionResponse{
Allowed: true,
AuditAnnotations: map[string]string{
"invalid*key": "value1",
},
},
})
default:
http.NotFound(w, r)
}

View File

@ -36,6 +36,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testing:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
],
)

View File

@ -23,15 +23,15 @@ import (
"time"
"github.com/golang/glog"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/api/admissionregistration/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config"
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
"k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
)
@ -116,6 +116,12 @@ func (d *validatingDispatcher) callHook(ctx context.Context, h *v1beta1.Webhook,
if response.Response == nil {
return &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Webhook response was absent")}
}
for k, v := range response.Response.AuditAnnotations {
key := h.Name + "/" + k
if err := attr.AddAnnotation(key, v); err != nil {
glog.Warningf("Failed to set admission audit annotation %s to %s for validating webhook %s: %v", key, v, h.Name, err)
}
}
if response.Response.Allowed {
return nil
}

View File

@ -21,6 +21,7 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/api/admission/v1beta1"
@ -72,7 +73,8 @@ func TestValidate(t *testing.T) {
continue
}
err = wh.Validate(webhooktesting.NewAttribute(ns, nil, tt.IsDryRun))
attr := webhooktesting.NewAttribute(ns, nil, tt.IsDryRun)
err = wh.Validate(attr)
if tt.ExpectAllow != (err == nil) {
t.Errorf("%s: expected allowed=%v, but got err=%v", tt.Name, tt.ExpectAllow, err)
}
@ -85,6 +87,16 @@ func TestValidate(t *testing.T) {
if _, isStatusErr := err.(*errors.StatusError); err != nil && !isStatusErr {
t.Errorf("%s: expected a StatusError, got %T", tt.Name, err)
}
fakeAttr, ok := attr.(*webhooktesting.FakeAttributes)
if !ok {
t.Errorf("Unexpected error, failed to convert attr to webhooktesting.FakeAttributes")
continue
}
if len(tt.ExpectAnnotations) == 0 {
assert.Empty(t, fakeAttr.GetAnnotations(), tt.Name+": annotations not set as expected.")
} else {
assert.Equal(t, tt.ExpectAnnotations, fakeAttr.GetAnnotations(), tt.Name+": annotations not set as expected.")
}
}
}