Skip to content

adds SSH signature validation for git commits#1141

Open
bb-Ricardo wants to merge 7 commits intofluxcd:mainfrom
bb-Ricardo:rb-feature/adds-ssh-signature-validation
Open

adds SSH signature validation for git commits#1141
bb-Ricardo wants to merge 7 commits intofluxcd:mainfrom
bb-Ricardo:rb-feature/adds-ssh-signature-validation

Conversation

@bb-Ricardo
Copy link

This PR adds support of SSH signature validation.

resolves: fluxcd/flux2#4145

  • adds new package git/signatures
  • adds validation of SSH signed commits to ssh_signature.go
  • moves GPG signature validation to gpg_signature.go
  • adds text fixtures for all SSH and GPG key types including commits and signatures
  • adds tests for all key/signature combinations
  • adds wrapper for "Verify(keyRings ...string)" function

- adds new package git/signatures
- adds validation of SSH signed commits to ssh_signature.go
- moves GPG signature validation to gpg_signature.go
- adds text fixtures for all SSH and GPG key types including commits and signatures
- adds tests for all key/signature combinations
- adds wrapper for "Verify(keyRings ...string)" function

Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
@bb-Ricardo bb-Ricardo force-pushed the rb-feature/adds-ssh-signature-validation branch from f814194 to 394fe64 Compare February 27, 2026 12:10
Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
@bb-Ricardo bb-Ricardo force-pushed the rb-feature/adds-ssh-signature-validation branch from 96523af to 1561774 Compare February 28, 2026 00:35
@stefanprodan
Copy link
Member

@bb-Ricardo please run make tidy and force push to unblock the test.

@bb-Ricardo bb-Ricardo requested a review from a team as a code owner February 28, 2026 08:48
Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
@bb-Ricardo bb-Ricardo force-pushed the rb-feature/adds-ssh-signature-validation branch from eedb46c to 048e862 Compare February 28, 2026 09:07
// in the format used by SSH (e.g., "SHA256:abc123...").
func GetPublicKeyFingerprint(pubKey gossh.PublicKey) string {
hash := sha256.Sum256(pubKey.Marshal())
return "SHA256:" + strings.TrimSuffix(base64.StdEncoding.EncodeToString(hash[:]), "=")
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use base64.RawStdEncoding which omits padding entirely.

Copy link
Author

Choose a reason for hiding this comment

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

thank you, will change it accordingly.

Copy link
Author

Choose a reason for hiding this comment

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

has been fixed


// Isx509Signature tests if the given signature is of type x509.
// It returns true if the signature starts with the x509 signature prefix.
func Isx509Signature(signature string) bool {
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
func Isx509Signature(signature string) bool {
func IsX509Signature(signature string) bool {

We do not support X509, why have this code here?

Copy link
Author

Choose a reason for hiding this comment

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

This is a place holder / compatibility implementation:

  1. to embed the signature type into the error message to inform the user about the wrong type of signature
  2. it is planned to implement x509 signature validation as well: Feature Request: support validation of additional git commit signature types source-controller#1996

Copy link
Member

Choose a reason for hiding this comment

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

Ok can you please add a comment and explain all of this. Also normalize the naming instead of Isx should be IsX .

Copy link
Author

Choose a reason for hiding this comment

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

Sure, will do that. So due to the CameCasing the x in x509 would be capitalized?

In general, these functions should be implemented in go-git but this is currently not the case. But the discussion about the git signature validation improvements are already ongoing.

Copy link
Author

Choose a reason for hiding this comment

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

changed all occurrences

return GetPublicKeyFingerprint(pubKey), nil
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

The hash algo is specified in the SSH signature. So instead of trying both algos, we can do:

err := sshsig.Verify(bytes.NewReader(payload), sig, pubKey, sig.HashAlgorithm, "git")
if err == nil {
    return GetPublicKeyFingerprint(pubKey), nil
}

Copy link
Author

Choose a reason for hiding this comment

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

thank you, will have a look into changing it.

Copy link
Author

Choose a reason for hiding this comment

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

changed it


for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sig, err := sshsig.Unarmor([]byte(tt.sig))
Copy link
Member

Choose a reason for hiding this comment

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

Why are we testing sshsig here? call VerifySSHSignature or ParseAuthorizedKeys instead?

Copy link
Author

Choose a reason for hiding this comment

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

Test cases have been combined and redundant tests have been removed.

})
}

func TestVerifySSHSignatureAllKeyTypes(t *testing.T) {
Copy link
Member

@stefanprodan stefanprodan Feb 28, 2026

Choose a reason for hiding this comment

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

This looks like a duplicate of TestVerifySSHSignature, if you delete it, does the test coverage drops?


// getPublicKeyFingerprint returns the SHA256 fingerprint of the public key
// in the format used by SSH (e.g., "SHA256:abc123...").
func GetPublicKeyFingerprint(pubKey gossh.PublicKey) string {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to export this?

Copy link
Author

@bb-Ricardo bb-Ricardo Feb 28, 2026

Choose a reason for hiding this comment

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

I wanted to use BuildCommitWithRef from clone. But to avoid circular dependencies, I needed to make this function public. I could put the test for the fingerprints into a separate test package to avoid that. Otherwise I would need to reimplement the behaviour of BuildCommitWithRef mockup, but wanted to avoid that to get some meaningful test results.

Copy link
Author

@bb-Ricardo bb-Ricardo Mar 2, 2026

Choose a reason for hiding this comment

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

I have split the test packages and now the function is not exported anymore.

Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
Signed-off-by: Ricardo Bartels <ricardo.bartels@telekom.de>
@bb-Ricardo bb-Ricardo force-pushed the rb-feature/adds-ssh-signature-validation branch from e247a34 to 5e6ab4d Compare March 2, 2026 23:16
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.

2 participants