Skip to content

Commit

Permalink
Add certificate bundle metadata endpoint
Browse files Browse the repository at this point in the history
For situations where it's easier to ask the API for the CA bundle
rather than send it via userdata, we can use this new endpoint.

Signed-off-by: Gabriel Adrian Samfira <[email protected]>
  • Loading branch information
gabriel-samfira committed Aug 24, 2023
1 parent cca522c commit 9c38138
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 0 deletions.
17 changes: 17 additions & 0 deletions apiserver/controllers/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,20 @@ func (a *APIController) SystemdUnitFileHandler(w http.ResponseWriter, r *http.Re
log.Printf("failed to encode response: %q", err)
}
}

func (a *APIController) RootCertificateBundleHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

bundle, err := a.r.GetRootCertificateBundle(ctx)
if err != nil {
handleError(w, err)
return
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(bundle); err != nil {
log.Printf("failed to encode response: %q", err)
}
}

// GetRootCertificateBundle
2 changes: 2 additions & 0 deletions apiserver/routers/routers.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddl
// Systemd files
metadataRouter.Handle("/system/service-name/", http.HandlerFunc(han.SystemdServiceNameHandler)).Methods("GET", "OPTIONS")
metadataRouter.Handle("/system/service-name", http.HandlerFunc(han.SystemdServiceNameHandler)).Methods("GET", "OPTIONS")
metadataRouter.Handle("/system/cert-bundle/", http.HandlerFunc(han.RootCertificateBundleHandler)).Methods("GET", "OPTIONS")
metadataRouter.Handle("/system/cert-bundle", http.HandlerFunc(han.RootCertificateBundleHandler)).Methods("GET", "OPTIONS")
metadataRouter.Handle("/systemd/unit-file/", http.HandlerFunc(han.SystemdUnitFileHandler)).Methods("GET", "OPTIONS")
metadataRouter.Handle("/systemd/unit-file", http.HandlerFunc(han.SystemdUnitFileHandler)).Methods("GET", "OPTIONS")

Expand Down
38 changes: 38 additions & 0 deletions params/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
package params

import (
"bytes"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"time"

commonParams "github.com/cloudbase/garm-provider-common/params"
Expand Down Expand Up @@ -411,6 +415,36 @@ type GithubCredentials struct {
CABundle []byte `json:"ca_bundle,omitempty"`
}

func (g GithubCredentials) RootCertificateBundle() (CertificateBundle, error) {
if len(g.CABundle) == 0 {
return CertificateBundle{}, nil
}

ret := map[string][]byte{}

var block *pem.Block
var rest []byte = g.CABundle
for {
block, rest = pem.Decode(rest)
if block == nil {
break
}
pub, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return CertificateBundle{}, err
}
out := &bytes.Buffer{}
if err := pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: block.Bytes}); err != nil {
return CertificateBundle{}, err
}
ret[fmt.Sprintf("%d", pub.SerialNumber)] = out.Bytes()
}

return CertificateBundle{
RootCertificates: ret,
}, nil
}

// used by swagger client generated code
type Credentials []GithubCredentials

Expand Down Expand Up @@ -514,3 +548,7 @@ type HookInfo struct {
Active bool `json:"active"`
InsecureSSL bool `json:"insecure_ssl"`
}

type CertificateBundle struct {
RootCertificates map[string][]byte `json:"root_certificates"`
}
2 changes: 2 additions & 0 deletions runner/common/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type PoolManager interface {
GetWebhookInfo(ctx context.Context) (params.HookInfo, error)
UninstallWebhook(ctx context.Context) error

RootCABundle() (params.CertificateBundle, error)

// PoolManager lifecycle functions. Start/stop pool.
Start() error
Stop() error
Expand Down
23 changes: 23 additions & 0 deletions runner/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,26 @@ func (r *Runner) GetInstanceGithubRegistrationToken(ctx context.Context) (string

return token, nil
}

func (r *Runner) GetRootCertificateBundle(ctx context.Context) (params.CertificateBundle, error) {
instance, err := auth.InstanceParams(ctx)
if err != nil {
log.Printf("failed to get instance params: %s", err)
return params.CertificateBundle{}, runnerErrors.ErrUnauthorized
}

poolMgr, err := r.getPoolManagerFromInstance(ctx, instance)
if err != nil {
return params.CertificateBundle{}, errors.Wrap(err, "fetching pool manager for instance")
}

bundle, err := poolMgr.RootCABundle()
if err != nil {
log.Printf("failed to get root CA bundle: %s", err)
// The root CA bundle is invalid. Return an empty bundle to the runner and log the event.
return params.CertificateBundle{
RootCertificates: make(map[string][]byte),
}, nil
}
return bundle, nil
}
4 changes: 4 additions & 0 deletions runner/pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -1701,3 +1701,7 @@ func (r *basePoolManager) UninstallWebhook(ctx context.Context) error {
func (r *basePoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
return r.helper.GetHookInfo(ctx)
}

func (r *basePoolManager) RootCABundle() (params.CertificateBundle, error) {
return r.credsDetails.RootCertificateBundle()
}

0 comments on commit 9c38138

Please sign in to comment.