From 1452c1cc718006c72c4b7876d4b3c0a08281074e Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Tue, 25 Oct 2016 11:45:33 +0200 Subject: [PATCH] pkg/authorization: send request's TLS peer certificates to plugins Signed-off-by: Antonio Murdaca --- pkg/authorization/api.go | 34 ++++++++++++++++++++++++++++++++++ pkg/authorization/authz.go | 7 +++++++ 2 files changed, 41 insertions(+) diff --git a/pkg/authorization/api.go b/pkg/authorization/api.go index fc82c46b01..05c75f1a67 100644 --- a/pkg/authorization/api.go +++ b/pkg/authorization/api.go @@ -1,5 +1,11 @@ package authorization +import ( + "crypto/x509" + "encoding/json" + "encoding/pem" +) + const ( // AuthZApiRequest is the url for daemon request authorization AuthZApiRequest = "AuthZPlugin.AuthZReq" @@ -11,6 +17,31 @@ const ( AuthZApiImplements = "authz" ) +// PeerCertificate is a wrapper around x509.Certificate which provides a sane +// enconding/decoding to/from PEM format and JSON. +type PeerCertificate x509.Certificate + +// MarshalJSON returns the JSON encoded pem bytes of a PeerCertificate. +func (pc *PeerCertificate) MarshalJSON() ([]byte, error) { + b := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: pc.Raw}) + return json.Marshal(b) +} + +// UnmarshalJSON populates a new PeerCertificate struct from JSON data. +func (pc *PeerCertificate) UnmarshalJSON(b []byte) error { + var buf []byte + if err := json.Unmarshal(b, &buf); err != nil { + return err + } + derBytes, _ := pem.Decode(buf) + c, err := x509.ParseCertificate(derBytes.Bytes) + if err != nil { + return err + } + *pc = PeerCertificate(*c) + return nil +} + // Request holds data required for authZ plugins type Request struct { // User holds the user extracted by AuthN mechanism @@ -31,6 +62,9 @@ type Request struct { // RequestHeaders stores the raw request headers sent to the docker daemon RequestHeaders map[string]string `json:"RequestHeaders,omitempty"` + // RequestPeerCertificates stores the request's TLS peer certificates in PEM format + RequestPeerCertificates []*PeerCertificate `json:"RequestPeerCertificates,omitempty"` + // ResponseStatusCode stores the status code returned from docker daemon ResponseStatusCode int `json:"ResponseStatusCode,omitempty"` diff --git a/pkg/authorization/authz.go b/pkg/authorization/authz.go index 9080249b5e..6e25d66f22 100644 --- a/pkg/authorization/authz.go +++ b/pkg/authorization/authz.go @@ -78,6 +78,13 @@ func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error { RequestHeaders: headers(r.Header), } + if r.TLS != nil { + for _, c := range r.TLS.PeerCertificates { + pc := PeerCertificate(*c) + ctx.authReq.RequestPeerCertificates = append(ctx.authReq.RequestPeerCertificates, &pc) + } + } + for i, plugin := range ctx.plugins { logrus.Debugf("AuthZ request using plugin %s", plugin.Name())