Skip to content

Commit

Permalink
set GVK on AdmissionReview responses in webhook (hashicorp#296)
Browse files Browse the repository at this point in the history
also fix typo in webhook deploy manifests
  • Loading branch information
ravilr authored Sep 11, 2021
1 parent f52b2f8 commit b79d59b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
2 changes: 1 addition & 1 deletion agent-inject/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (a *Agent) newConfig(init bool) ([]byte, error) {
},
Templates: a.newTemplateConfigs(),
TemplateConfig: &TemplateConfig{
ExitOnRetryFailure: a.VaultAgentTemplateConfig.ExitOnRetryFailure,
ExitOnRetryFailure: a.VaultAgentTemplateConfig.ExitOnRetryFailure,
StaticSecretRenderInterval: a.VaultAgentTemplateConfig.StaticSecretRenderInterval,
},
}
Expand Down
41 changes: 37 additions & 4 deletions agent-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ import (
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/mattbaird/jsonpatch"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
)

var (
deserializer = func() runtime.Decoder {
codecs := serializer.NewCodecFactory(runtime.NewScheme())
admissionScheme = runtime.NewScheme()
deserializer = func() runtime.Decoder {
codecs := serializer.NewCodecFactory(admissionScheme)
return codecs.UniversalDeserializer()
}

Expand All @@ -31,6 +35,11 @@ var (
}
)

func init() {
utilruntime.Must(admissionv1.AddToScheme(admissionScheme))
utilruntime.Must(v1beta1.AddToScheme(admissionScheme))
}

// Handler is the HTTP handler for admission webhooks.
type Handler struct {
// RequireAnnotation means that the annotation must be given to inject.
Expand Down Expand Up @@ -87,9 +96,18 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) {
return
}

var admReq admissionv1.AdmissionReview
var admResp admissionv1.AdmissionReview
if _, _, err := deserializer().Decode(body, nil, &admReq); err != nil {

// Both v1 and v1beta1 AdmissionReview types are exactly the same, so the v1beta1 type can
// be decoded into the v1 type. However the runtime codec's decoder guesses which type to
// decode into by type name if an Object's TypeMeta isn't set. By setting TypeMeta of an
// unregistered type to the v1 GVK, the decoder will coerce a v1beta1 AdmissionReview to v1.
// The actual AdmissionReview GVK will be used to write a typed response in case the
// webhook config permits multiple versions, otherwise this response will fail.
admReq := unversionedAdmissionReview{}
admReq.SetGroupVersionKind(admissionv1.SchemeGroupVersion.WithKind("AdmissionReview"))
_, actualAdmRevGVK, err := deserializer().Decode(body, nil, &admReq)
if err != nil {
msg := fmt.Sprintf("error decoding admission request: %s", err)
http.Error(w, msg, http.StatusInternalServerError)
h.Log.Error("error on request", "Error", msg, "Code", http.StatusInternalServerError)
Expand All @@ -98,6 +116,14 @@ func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) {
admResp.Response = h.Mutate(admReq.Request)
}

// Default to a v1 AdmissionReview, otherwise the API server may not recognize the request
// if multiple AdmissionReview versions are permitted by the webhook config.
if actualAdmRevGVK == nil || *actualAdmRevGVK == (schema.GroupVersionKind{}) {
admResp.SetGroupVersionKind(admissionv1.SchemeGroupVersion.WithKind("AdmissionReview"))
} else {
admResp.SetGroupVersionKind(*actualAdmRevGVK)
}

resp, err := json.Marshal(&admResp)
if err != nil {
msg := fmt.Sprintf("error marshalling admission response: %s", err)
Expand Down Expand Up @@ -210,3 +236,10 @@ func admissionError(err error) *admissionv1.AdmissionResponse {
},
}
}

// unversionedAdmissionReview is used to decode both v1 and v1beta1 AdmissionReview types.
type unversionedAdmissionReview struct {
admissionv1.AdmissionReview
}

var _ runtime.Object = &unversionedAdmissionReview{}
2 changes: 1 addition & 1 deletion deploy/injector-mutating-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ webhooks:
sideEffects: None
admissionReviewVersions:
- "v1"
- "v1beta"
- "v1beta1"
clientConfig:
service:
name: vault-agent-injector-svc
Expand Down

0 comments on commit b79d59b

Please sign in to comment.