Skip to content

Conversation

@gerardsn
Copy link
Member

@gerardsn gerardsn commented Jun 12, 2023

closes #2018 alternative solution to #2235

DenyList.Subscribers get pinged when the Denylist is updated (revalidation is not performed when Denylist is not configured). What to do with this information is determined by the subscriber. The connection manager verifies the certificate of all peers and disconnects those that are no longer valid.

diagnostics also show the last time the certificate was updated, which is zero if the denylist is not used

network:
    connections:
        certificates_last_validated: 0001-01-01T00:00:00Z
        connected_peers:
            - id: ...


// err status is set on connection. Due to EOF it's an unknown error
assert.Equal(t, codes.Unknown, connection.status.Load().Code())
// Last received message is dropped and no status is set. Default value is OK.
Copy link
Member

Choose a reason for hiding this comment

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

This is a bit weird, status is now the same as being operational. Shouldn't it be a disconnected status somehow?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know what the right solution is here.

connection.status is a grpc Status that reflects the state of the last message received. (it is a bit of a hack for the backoff) no-status is considered equal to OK (this situation I think)

When the connection's context is cancelled it means that the receiving side closed the connection. conn.startReceiving ignores any future message (including any possible errors) in this case and the status of the last processed incoming message was still ok.

Also, Unauthenticated is the only status we act on and does not apply here, all other statuses are handled the same as the current situation.

Copy link
Member Author

Choose a reason for hiding this comment

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

This test is weird anyway. It supposedly tests conn.startSending, but the only thing it tests is error handling of conn.startReceiving after disconnect with a stub stream that simulates stream closure with an EOF message

@gerardsn gerardsn requested a review from woutslakhorst June 16, 2023 10:51
case <-mc.ctx.Done():
// disconnect: drop message and stop receiving
return
default:
Copy link
Member

Choose a reason for hiding this comment

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

interesting pattern, but note that RecvMsg is blocking anyway, so you could just check ctx.Err() != nil?

Copy link
Member Author

@gerardsn gerardsn Jun 20, 2023

Choose a reason for hiding this comment

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

changed to check error

s.connections.forEach(func(conn Connection) {
peerCert := conn.Peer().Certificate
if nowFunc().After(peerCert.NotAfter) {
log.Logger().WithError(errors.New("certificate expired while in use")).WithFields(conn.Peer().ToFields()).Info("Disconnected peer")
Copy link
Member

Choose a reason for hiding this comment

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

why check this? This will be checked by the Golang's TLS when setting up the connection anyway?

Copy link
Member Author

Choose a reason for hiding this comment

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

because we're re-validating the peer's certificate on a connection that may last for a month? The only things that could have changed since it was first accepted is that it is banned or expired.


// Notify all subscribers synchronously
for _, sub := range b.subscribers {
sub()
Copy link
Member

Choose a reason for hiding this comment

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

can conn.disconnect() block when the other side is a slow responder (closing TCP involves sending packets to thw other side)? Since subscribers are called synchronously?

Copy link
Member Author

@gerardsn gerardsn Jun 20, 2023

Choose a reason for hiding this comment

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

conn.disconnect() does not depend on the peer, so no


// SubscribeDenied registers a callback that is triggered everytime the denylist is updated.
// This can be used to revalidate all certificates on long-lasting connections by calling Validate on them again.
SubscribeDenied(f func())
Copy link
Member

Choose a reason for hiding this comment

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

SubscribeUpdated?

Copy link
Member Author

Choose a reason for hiding this comment

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

You only subscribe to updates on the denylist, so I wanted to have something indicating that in the name.

@gerardsn gerardsn merged commit 6646c9f into master Jun 20, 2023
@gerardsn gerardsn deleted the network/periodically-validate-connection-certificate branch June 20, 2023 11:15
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.

Network: close connection if certificate is revoked while connected

4 participants