示例#1
0
// 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())
}
示例#2
0
// 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))
}