From 904f416d202b1dbf8df220971bd0b86cd1a41ff3 Mon Sep 17 00:00:00 2001 From: Josh Drake Date: Mon, 24 Jul 2023 00:29:22 -0500 Subject: [PATCH 1/2] Include authorization principal in provisioner webhooks. --- authority/provisioner/aws.go | 13 +++++++++++-- authority/provisioner/azure.go | 15 ++++++++++++--- authority/provisioner/gcp.go | 13 +++++++++++-- authority/provisioner/x5c.go | 14 ++++++++++++-- webhook/options.go | 7 +++++++ webhook/types.go | 2 ++ 6 files changed, 55 insertions(+), 9 deletions(-) diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index b30292fd..11b18ebb 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -24,6 +24,7 @@ import ( "go.step.sm/linkedca" "github.com/smallstep/certificates/errs" + "github.com/smallstep/certificates/webhook" ) // awsIssuer is the string used as issuer in the generated tokens. @@ -521,7 +522,11 @@ func (p *AWS) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro commonNameValidator(payload.Claims.Subject), newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), - p.ctl.newWebhookController(data, linkedca.Webhook_X509), + p.ctl.newWebhookController( + data, + linkedca.Webhook_X509, + webhook.WithAuthorizationPrincipal(doc.InstanceID), + ), ), nil } @@ -804,6 +809,10 @@ func (p *AWS) AuthorizeSSHSign(_ context.Context, token string) ([]SignOption, e // Ensure that all principal names are allowed newSSHNamePolicyValidator(p.ctl.getPolicy().getSSHHost(), nil), // Call webhooks - p.ctl.newWebhookController(data, linkedca.Webhook_SSH), + p.ctl.newWebhookController( + data, + linkedca.Webhook_SSH, + webhook.WithAuthorizationPrincipal(doc.InstanceID), + ), ), nil } diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index c88a098d..1c70a132 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -20,6 +20,7 @@ import ( "go.step.sm/linkedca" "github.com/smallstep/certificates/errs" + "github.com/smallstep/certificates/webhook" ) // azureOIDCBaseURL is the base discovery url for Microsoft Azure tokens. @@ -403,7 +404,11 @@ func (p *Azure) AuthorizeSign(_ context.Context, token string) ([]SignOption, er defaultPublicKeyValidator{}, newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), - p.ctl.newWebhookController(data, linkedca.Webhook_X509), + p.ctl.newWebhookController( + data, + linkedca.Webhook_X509, + webhook.WithAuthorizationPrincipal(identityObjectID), + ), ), nil } @@ -421,7 +426,7 @@ func (p *Azure) AuthorizeSSHSign(_ context.Context, token string) ([]SignOption, return nil, errs.Unauthorized("azure.AuthorizeSSHSign; sshCA is disabled for provisioner '%s'", p.GetName()) } - _, name, _, _, _, err := p.authorizeToken(token) + _, name, _, _, identityObjectID, err := p.authorizeToken(token) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "azure.AuthorizeSSHSign") } @@ -473,7 +478,11 @@ func (p *Azure) AuthorizeSSHSign(_ context.Context, token string) ([]SignOption, // Ensure that all principal names are allowed newSSHNamePolicyValidator(p.ctl.getPolicy().getSSHHost(), nil), // Call webhooks - p.ctl.newWebhookController(data, linkedca.Webhook_SSH), + p.ctl.newWebhookController( + data, + linkedca.Webhook_SSH, + webhook.WithAuthorizationPrincipal(identityObjectID), + ), ), nil } diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index 2b5b932b..8634fecc 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -21,6 +21,7 @@ import ( "go.step.sm/linkedca" "github.com/smallstep/certificates/errs" + "github.com/smallstep/certificates/webhook" ) // gcpCertsURL is the url that serves Google OAuth2 public keys. @@ -275,7 +276,11 @@ func (p *GCP) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro defaultPublicKeyValidator{}, newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), - p.ctl.newWebhookController(data, linkedca.Webhook_X509), + p.ctl.newWebhookController( + data, + linkedca.Webhook_X509, + webhook.WithAuthorizationPrincipal(ce.InstanceID), + ), ), nil } @@ -442,6 +447,10 @@ func (p *GCP) AuthorizeSSHSign(_ context.Context, token string) ([]SignOption, e // Ensure that all principal names are allowed newSSHNamePolicyValidator(p.ctl.getPolicy().getSSHHost(), nil), // Call webhooks - p.ctl.newWebhookController(data, linkedca.Webhook_SSH), + p.ctl.newWebhookController( + data, + linkedca.Webhook_SSH, + webhook.WithAuthorizationPrincipal(ce.InstanceID), + ), ), nil } diff --git a/authority/provisioner/x5c.go b/authority/provisioner/x5c.go index f0b08826..be606ae8 100644 --- a/authority/provisioner/x5c.go +++ b/authority/provisioner/x5c.go @@ -248,7 +248,12 @@ func (p *X5C) AuthorizeSign(_ context.Context, token string) ([]SignOption, erro defaultPublicKeyValidator{}, newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()), newX509NamePolicyValidator(p.ctl.getPolicy().getX509()), - p.ctl.newWebhookController(data, linkedca.Webhook_X509, webhook.WithX5CCertificate(x5cLeaf)), + p.ctl.newWebhookController( + data, + linkedca.Webhook_X509, + webhook.WithX5CCertificate(x5cLeaf), + webhook.WithAuthorizationPrincipal(x5cLeaf.Subject.CommonName), + ), }, nil } @@ -338,6 +343,11 @@ func (p *X5C) AuthorizeSSHSign(_ context.Context, token string) ([]SignOption, e // Ensure that all principal names are allowed newSSHNamePolicyValidator(p.ctl.getPolicy().getSSHHost(), p.ctl.getPolicy().getSSHUser()), // Call webhooks - p.ctl.newWebhookController(data, linkedca.Webhook_SSH, webhook.WithX5CCertificate(x5cLeaf)), + p.ctl.newWebhookController( + data, + linkedca.Webhook_SSH, + webhook.WithX5CCertificate(x5cLeaf), + webhook.WithAuthorizationPrincipal(x5cLeaf.Subject.CommonName), + ), ), nil } diff --git a/webhook/options.go b/webhook/options.go index 0e82e68c..86923709 100644 --- a/webhook/options.go +++ b/webhook/options.go @@ -68,6 +68,13 @@ func WithAttestationData(data *AttestationData) RequestBodyOption { } } +func WithAuthorizationPrincipal(p string) RequestBodyOption { + return func(rb *RequestBody) error { + rb.AuthorizationPrincipal = p + return nil + } +} + func WithSSHCertificateRequest(cr sshutil.CertificateRequest) RequestBodyOption { return func(rb *RequestBody) error { rb.SSHCertificateRequest = &SSHCertificateRequest{ diff --git a/webhook/types.go b/webhook/types.go index 02f36b56..9eda0578 100644 --- a/webhook/types.go +++ b/webhook/types.go @@ -84,4 +84,6 @@ type RequestBody struct { SCEPTransactionID string `json:"scepTransactionID,omitempty"` // Only set for X5C provisioners X5CCertificate *X5CCertificate `json:"x5cCertificate,omitempty"` + // Set for X5C, AWS, GCP, and Azure provisioners + AuthorizationPrincipal string `json:"authorizationPrincipal,omitempty"` } From ff424fa9443ad37872374a2b8b2e0f756058ff95 Mon Sep 17 00:00:00 2001 From: Josh Drake Date: Mon, 24 Jul 2023 15:27:49 -0500 Subject: [PATCH 2/2] Fix tests. --- authority/provisioner/x5c_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index ec3e0c73..f9a2604b 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -499,7 +499,7 @@ func TestX5C_AuthorizeSign(t *testing.T) { case *WebhookController: assert.Len(t, 0, v.webhooks) assert.Equals(t, linkedca.Webhook_X509, v.certType) - assert.Len(t, 1, v.options) + assert.Len(t, 2, v.options) default: assert.FatalError(t, fmt.Errorf("unexpected sign option of type %T", v)) } @@ -805,7 +805,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { case *WebhookController: assert.Len(t, 0, v.webhooks) assert.Equals(t, linkedca.Webhook_SSH, v.certType) - assert.Len(t, 1, v.options) + assert.Len(t, 2, v.options) default: assert.FatalError(t, fmt.Errorf("unexpected sign option of type %T", v)) }