Skip to content

Commit

Permalink
Add a hourly goroutine that forces update of the CRL
Browse files Browse the repository at this point in the history
The CRL has an validity period. Vault automatically recreates the CRL, with
new validity times, when adding certificates to the CRL. But in our use case,
the certificates are long lived and the CRL could be not updated in quite some
time. Instead instructing the user to configure a big lease time for the CRL,
use a cront task to force hourly recreation (rotate)of it.
  • Loading branch information
roivaz committed Jan 28, 2020
1 parent 5850802 commit 0cf7956
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 5 deletions.
31 changes: 27 additions & 4 deletions cmd/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/google/go-github/github"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/robfig/cron"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/oauth2"
Expand Down Expand Up @@ -142,7 +143,7 @@ func runServer(cmd *cobra.Command, args []string) {
Address: viper.GetString("vault-addr"),
Token: viper.GetString("vault-auth-token"),
}
api(vc)
start(vc)
} else if viper.IsSet("vault-auth-approle-role-id") &&
viper.IsSet("vault-auth-approle-secret-id") &&
viper.IsSet("vault-auth-approle-backend-path") {
Expand All @@ -153,14 +154,36 @@ func runServer(cmd *cobra.Command, args []string) {
SecretID: viper.GetString("vault-auth-approle-secret-id"),
BackendPath: viper.GetString("vault-auth-approle-backend-path"),
}
api(vc)
start(vc)
} else {
panic("Vault auth config options missing")
}
}

func api(vc vault.AuthenticatedClient) {
// Use gorilla/mux as http router
func start(vc vault.AuthenticatedClient) {
// Start RotateCRL cron like task
client, err := vc.GetClient()
if err != nil {
panic("Failed while creating Vault client")
}
c := cron.New()
c.AddFunc("@every 1m", func() {
err = operations.RotateCRL(
&operations.RotateCRLRequest{
Client: client,
VaultPKIPath: viper.GetStringSlice("vault-pki-paths")[len(viper.GetStringSlice("vault-pki-paths"))-1],
ClientVPNEndpointID: viper.GetString("client-vpn-endpoint-id"),
})
if err != nil {
log.Println("Cron procesor failed trying to rotate the CRL")
log.Fatal(err)
} else {
log.Println("Vault CRL rotated by cron processor")
}
})
c.Start()

// Start the server
mux := mux.NewRouter()
mux.HandleFunc("/crl", getCRLHandler(vc)).Methods(http.MethodGet)
mux.HandleFunc("/crl", updateCRLHandler(vc)).Methods(http.MethodPost)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/hashicorp/vault/api v1.0.4
github.com/hashicorp/vault/sdk v0.1.13
github.com/pkg/errors v0.8.0
github.com/robfig/cron v1.2.0
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.6.1
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
Expand Down
35 changes: 34 additions & 1 deletion pkg/operations/crl.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func UpdateCRL(r *UpdateCRLRequest) ([]byte, error) {
return nil, err
}

//For each user, get the list of certificates, and revoke all of the but the latest
//For each user, get the list of certificates, and revoke all of them but the latest
for _, crts := range users {
err := revokeUserCertificates(r.Client, r.VaultPKIPath, crts, false)
if err != nil {
Expand All @@ -77,6 +77,9 @@ func UpdateCRL(r *UpdateCRLRequest) ([]byte, error) {
&ec2.ExportClientVpnClientCertificateRevocationListInput{
ClientVpnEndpointId: aws.String(r.ClientVPNEndpointID),
})
if err != nil {
return nil, err
}

// Handle the case that no CRL has been uploaded yet. The API
// will return a struct without the 'CertificateRevocationList'
Expand Down Expand Up @@ -104,10 +107,40 @@ func UpdateCRL(r *UpdateCRLRequest) ([]byte, error) {
CertificateRevocationList: aws.String(string(crl)),
ClientVpnEndpointId: aws.String(r.ClientVPNEndpointID),
})
log.Println("First upload of CRL to the CPN endpoint")
if err != nil {
return nil, err
}
}

return crl, nil
}

// RotateCRLRequest is the structure containing the
// required data to rotate the Client Revocation List
type RotateCRLRequest struct {
Client *api.Client
VaultPKIPath string
ClientVPNEndpointID string
}

func RotateCRL(r *RotateCRLRequest) error {

req := r.Client.NewRequest("GET", fmt.Sprintf("/v1/%s/crl/rotate", r.VaultPKIPath))
_, err := r.Client.RawRequest(req)
if err != nil {
return err
}

_, err = UpdateCRL(
&UpdateCRLRequest{
Client: r.Client,
VaultPKIPath: r.VaultPKIPath,
ClientVPNEndpointID: r.ClientVPNEndpointID,
})
if err != nil {
return err
}

return nil
}

0 comments on commit 0cf7956

Please sign in to comment.