Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add taint upstream authority #5340

Merged
merged 16 commits into from
Aug 16, 2024

Conversation

MarcosDY
Copy link
Collaborator

@MarcosDY MarcosDY commented Jul 30, 2024

Pull Request check list

  • Commit conforms to CONTRIBUTING.md?
  • Proper tests/regressions included?
  • Documentation updated?

Affected functionality
no actual functionalities are affected

Description of change
To taint a local authority that is using an upstream authority, we need a way to taint the upstream authority itself and rotate intermediates + SVIDs using that tainted upstream authority.
This PR aims to add a new RPC that allows tainting an upstream authority using SKID as the identifier, update the datastore with that information, and propagate it to downstream servers.
This PR is not forcing rotation but only propagating tainted authorities. Forcing rotations will happen in other PRs.

Changes to the SDK can be found here.

Which issue this PR fixes
fixes #3899, #3893, #3900

@MarcosDY MarcosDY force-pushed the poc-taint-upstream-authority branch 2 times, most recently from 7b19089 to a429675 Compare August 6, 2024 13:30
@MarcosDY MarcosDY changed the title POC to add taint upstream authority Add taint upstream authority Aug 12, 2024
@MarcosDY MarcosDY marked this pull request as ready for review August 12, 2024 15:07
}

func toProtoFields(jwtKey JWTKey) (string, []byte, int64, error) {
func toProtoFields(jwtKey JWTKey) (string, []byte, int64, bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's becoming more difficult to guess what each return value means in this function. I think that it would be good to have named return values as an easy way to document the meaning of each of them.

if req.AuthorityId != "" {
log = log.WithField(telemetry.LocalAuthorityID, req.AuthorityId)
}

if s.ca.IsUpstreamAuthority() {
return nil, api.MakeErr(log, codes.FailedPrecondition, "local authority can't be tainted if there is an upstream authorit", nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, api.MakeErr(log, codes.FailedPrecondition, "local authority can't be tainted if there is an upstream authorit", nil)
return nil, api.MakeErr(log, codes.FailedPrecondition, "local authority can't be tainted if there is an upstream authority", nil)

@@ -541,6 +541,9 @@ const (
// with other tags to add clarity
Subject = "subject"

// Subject tags a certificate subject key ID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Subject tags a certificate subject key ID
// SubjectKeyID tags a certificate subject key ID

}

rpccontext.AuditRPC(ctx)
log.Info("X.509 upstream authority revoked successfully")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.Info("X.509 upstream authority revoked successfully")
log.Info("X.509 upstream authority successfully revoked")

return "", nil, err
nextSlot := s.ca.GetNextX509CASlot()
if subjectKeyIDRequest != nextSlot.UpstreamAuthorityID() {
return errors.New("upstream authority is not signing Old local authority")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return errors.New("upstream authority is not signing Old local authority")
return errors.New("upstream authority didn't sign the old local authority")

bundle.X509TaintedKeys = append(bundle.X509TaintedKeys, &common.X509TaintedKey{PublicKey: pKey})
if !found {
return status.Errorf(codes.NotFound, "no ca found with provided subject key ID")
}

_, err = updateBundle(tx, bundle, nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should increment bundle.SequenceNumber before calling updateBundle, otherwise SequenceNumber will remain the same.

if !keyFound {
return status.Error(codes.NotFound, "no root CA found with provided subject key ID")
}

bundle.RootCas = rootCAs

if _, err := updateBundle(tx, bundle, nil); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should increment bundle.SequenceNumber before calling updateBundle, otherwise SequenceNumber will remain the same.

// No able to revoke untainted bundles
err = s.ds.RevokeX509CA(ctx, "spiffe://foo", s.cert.PublicKey)
spiretest.RequireGRPCStatus(t, err, codes.InvalidArgument, "it is not possible to revoke an untainted root CA")
t.Run("Unable to revoke untainted bundles", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to check that the sequence number of the bundle remains the same for those cases that fail.

{PublicKey: certPublicKeyRaw},
}
require.Equal(t, expectedTaintedKeys, fetchedBundle.X509TaintedKeys)
t.Run("no bundle with provided skID", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to check that the sequence number of the bundle remains the same for those cases that fail.


fetchedBundle, err := s.ds.FetchBundle(ctx, "spiffe://foo")
require.NoError(t, err)
t.Run("Revoke successfully", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to check that the sequence number of the bundle is incremented on successful operations.

@amartinezfayo
Copy link
Member

It's looking great! I think that we are missing propagating the tainted bit in some places:

@amartinezfayo
Copy link
Member

TestCommonBundleFromProto should capture the proper propagation of the tainted bit.
It doesn't seem like we have explicit tests for ParseX509Authorities and ParseJWTAuthorities?
We should make sure that propagation of the tainted bit is covered by tests in all those functions. We can handle that in a separate PR if that's more convenient.

Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
Signed-off-by: Marcos Yacob <[email protected]>
@MarcosDY MarcosDY force-pushed the poc-taint-upstream-authority branch from ae61b82 to ed3ef5a Compare August 16, 2024 14:05
@MarcosDY
Copy link
Collaborator Author

we discuss to add that propagation as part of #5394 to reduce changes to apply in this PR and it is not required for current PR functionality

Copy link
Member

@amartinezfayo amartinezfayo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 🚀

@amartinezfayo amartinezfayo merged commit e3dac17 into spiffe:main Aug 16, 2024
34 checks passed
@amartinezfayo amartinezfayo added this to the 1.10.2 milestone Aug 16, 2024
@MarcosDY MarcosDY linked an issue Aug 16, 2024 that may be closed by this pull request
@MarcosDY MarcosDY deleted the poc-taint-upstream-authority branch October 10, 2024 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Propagate Taint keys on SPIRE upstream authority Update NewDowstreamX509CA to propagate metadata
2 participants