// HandleCommandConnection is the initial point of contact on our main port. The protocol // implementation for inbound connections allows for identity exchange and signing prior to // upgrading to TLS. Once upgraded we will serve RPC to the agent. func (d *Director) HandleCommandConnection(conn net.Conn) { var ( err error cmd byte peerId string ) defer conn.Close() // setup a base logger so all messages include our address logger := log.WithFields(log.Fields{ "address": conn.RemoteAddr().String(), "type": "command", }) logger.Debug("New connection for Command RPC") proto := protocol.NewProtocol(conn) // Read our command cmd, err = proto.ReadByte() if err != nil { logger.WithError(err).Error("Failed to read command when setting up Control RPC") return } if cmd != protocol.TLS { logger.Error("Invalid command when setting up Control RPC") return } if peerId, err = proto.HandleStartTLS(d.identity, d.authority.Certificate); err != nil { logger.WithError(err).Error("Failed up handle Start TLS for Control RPC") return } // The connection is now upgraded to TLS and will be serving RPC to us // Load the agent's profile based on the peer ID from the TLS agent, ok := d.agents[peerId] if !ok { log.WithFields(log.Fields{ "peerId": peerId, }).Error("No agent found for peerId") return } /* if err != nil { log.WithError(err).Error("Failed to load agent profile") return }*/ // This will block agent.HandleConn(proto.Conn()) }
// HandleControlConnection ... func (d *Director) HandleControlConnection(conn net.Conn) { var ( err error cmd byte peerId string startTLS bool ) defer conn.Close() // setup a base logger so all messages include our address logger := log.WithFields(log.Fields{ "address": conn.RemoteAddr().String(), "type": "control", }) logger.Debug("New connection for Control RPC") proto := protocol.NewProtocol(conn) // Announce the protocol logger.Debug("Announcing protocol") if err = proto.Announce(); err != nil { log.WithError(err).Error("Protocol announcement failed") return } logger.Debug("Protocol announced") logger.Debug("Beginning TLS setup") startTLS = false for !startTLS { cmd, err = proto.ReadByte() if err != nil { logger.WithError(err).Error("Failed to read protocol command") return } switch cmd { case protocol.SigningRequest: logger.Debug("Reading signing request") request, err := proto.HandleSigningRequest() if err != nil { logger.WithError(err).Error("Failed to read signing request") return } // get the identity via the common name in the request logger.WithFields(log.Fields{ "name": request.Subject.CommonName, }).Debug("Loading identity") identity, err := d.state.LoadIdentity(request.Subject.CommonName) if err != nil { logger.WithFields(log.Fields{ "error": err, "id": request.Subject.CommonName, }).Error("Error while loading the identity") return } if identity == nil { // Invalid identity, this means we want to create a new identity for an admin to sign logger.WithFields(log.Fields{ "name": request.Subject.CommonName, }).Debug("Creating new identity") identity = security.NewIdentity(request.Subject.CommonName) identity.Request = request d.state.StoreIdentity(identity) d.state.AddIdentityToPending(identity) if err = proto.Ack(); err != nil { logger.WithError(err).Error("Failed to ack signing request") return } } else { // See if this identity has a certificate to send back if identity.Certificate != nil { logger.WithFields(log.Fields{ "name": request.Subject.CommonName, }).Debug("Sending signed certificate") if err = proto.Resp(); err != nil { logger.WithError(err).Error("Failed to signal response") return } proto.SendCertificate(identity.Certificate) proto.SendCertificate(d.authority.Certificate) } else { if err = proto.Ack(); err != nil { logger.WithError(err).Error("Failed to ack signing request") return } logger.WithFields(log.Fields{ "name": request.Subject.CommonName, }).Debug("Request is still pending") } } case protocol.TLS: logger.Info("Upgrading connection to TLS") if peerId, err = proto.HandleStartTLS(d.identity, d.authority.Certificate); err != nil { logger.WithError(err).Error("Failed up handle Start TLS") return } logger.WithFields(log.Fields{ "peerId": peerId, }).Debug("Upgraded!") // Load our identity. We don't actually care about the identity -- we just want to // make sure that it's valid and loads correctly based on this peer ID _, err := d.state.LoadIdentity(peerId) if err != nil { logger.WithError(err).Error("Failed to load Agent Identity") return } startTLS = true default: logger.WithFields(log.Fields{ "cmd": cmd, }).Error("Unknown command") return } } logger.Info("Control connection established, serving RPC") control.ServeConn(proto.Conn(), control.NewRPC(d)) }