Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/usage/stateful-applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Where:
* `$NAMESPACE_NAME` is the name of the namespace where the *PVC* lives in.
* `$TARGET_NODE_NAME` is the name of the node where the *PVC* will be moved to.

Under the hood, the migration process leverages the Liqo cross-cluster network fabric and the [Restic project](https://restic.net/) to back up the original data in a temporary repository, and then restore it in a brand-new *PVC* forced to be created in the target cluster.
Under the hood, the migration process leverages the Liqo cross-cluster network fabric and the [Restic project](https://github.com/restic/restic) to back up the original data in a temporary repository, and then restore it in a brand-new *PVC* forced to be created in the target cluster.

```{warning}
*Liqo* and *liqoctl* **are not** backup tools. Make sure to properly back up important data before starting the migration process.
Expand Down
15 changes: 13 additions & 2 deletions pkg/liqo-controller-manager/authentication/csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,24 @@ func checkCSR(csr, publicKey []byte, checkPublicKey bool, commonName, organizati
return fmt.Errorf("invalid public key")
}

// Marshal CSR public key to PKIX DER and compare with provided PKIX public key bytes
// Parse the provided public key (supports PEM, PKIX DER, or raw Ed25519)
parsedPubKey, err := parsePublicKey(publicKey)
if err != nil {
return fmt.Errorf("failed to parse provided public key: %w", err)
}

// Marshal both keys to PKIX DER for comparison
csrPubDER, err := x509.MarshalPKIXPublicKey(x509Csr.PublicKey)
if err != nil {
return fmt.Errorf("failed to marshal CSR public key: %w", err)
}

if !bytes.Equal(csrPubDER, publicKey) {
parsedPubDER, err := x509.MarshalPKIXPublicKey(parsedPubKey)
if err != nil {
return fmt.Errorf("failed to marshal provided public key: %w", err)
}

if !bytes.Equal(csrPubDER, parsedPubDER) {
return fmt.Errorf("invalid public key")
}
}
Expand Down
33 changes: 30 additions & 3 deletions pkg/liqo-controller-manager/authentication/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,37 @@ func SignNonce(priv crypto.PrivateKey, nonce []byte) ([]byte, error) {
}
}

// VerifyNonce verifies the signature of a nonce using the PKIX-encoded public key bytes of the cluster.
// parsePublicKey parses a public key from various formats:
// - PKIX DER-encoded bytes
// - PEM-encoded public key
// - Raw Ed25519 public key bytes (32 bytes)
func parsePublicKey(pubKeyBytes []byte) (crypto.PublicKey, error) {
// Try PEM decoding first
if block, _ := pem.Decode(pubKeyBytes); block != nil {
pubKeyBytes = block.Bytes
}

// Try PKIX parsing
if pub, err := x509.ParsePKIXPublicKey(pubKeyBytes); err == nil {
return pub, nil
}

// Try raw Ed25519 public key (32 bytes)
if len(pubKeyBytes) == ed25519.PublicKeySize {
return ed25519.PublicKey(pubKeyBytes), nil
}

return nil, fmt.Errorf("unable to parse public key: unrecognized format (length: %d)", len(pubKeyBytes))
}

// VerifyNonce verifies the signature of a nonce using the public key bytes of the cluster.
// The public key can be Ed25519, RSA, or ECDSA.
func VerifyNonce(pubKeyPKIX, nonce, signature []byte) (bool, error) {
pub, err := x509.ParsePKIXPublicKey(pubKeyPKIX)
// It accepts the public key in multiple formats:
// - PKIX DER-encoded bytes
// - PEM-encoded public key (will be decoded first)
// - Raw Ed25519 public key bytes (32 bytes)
func VerifyNonce(pubKeyBytes, nonce, signature []byte) (bool, error) {
pub, err := parsePublicKey(pubKeyBytes)
if err != nil {
return false, fmt.Errorf("failed to parse public key: %w", err)
}
Expand Down
Loading