func revokeBySerial(serial string, reasonCode core.RevocationCode, deny bool, cac rpc.CertificateAuthorityClient, auditlogger *blog.AuditLogger, tx *gorp.Transaction) (err error) { if reasonCode < 0 || reasonCode == 7 || reasonCode > 10 { panic(fmt.Sprintf("Invalid reason code: %d", reasonCode)) } certObj, err := tx.Get(core.Certificate{}, serial) if err != nil { return } certificate, ok := certObj.(*core.Certificate) if !ok { err = fmt.Errorf("Cast failure") return } if deny { // Retrieve DNS names associated with serial var cert *x509.Certificate cert, err = x509.ParseCertificate(certificate.DER) if err != nil { return } err = addDeniedNames(tx, append(cert.DNSNames, cert.Subject.CommonName)) if err != nil { return } } err = cac.RevokeCertificate(certificate.Serial, reasonCode) if err != nil { return } auditlogger.Info(fmt.Sprintf("Revoked certificate %s with reason '%s'", serial, core.RevocationReasons[reasonCode])) return }
// RunUntilSignaled starts the server and run until we get something on closeChan func RunUntilSignaled(logger *blog.AuditLogger, server *rpc.AmqpRPCServer, closeChan chan *amqp.Error) { server.Start() fmt.Fprintf(os.Stderr, "Server running...\n") // Block until channel closes err := <-closeChan logger.Warning(fmt.Sprintf("AMQP Channel closed, will reconnect in 5 seconds: [%s]", err)) time.Sleep(time.Second * 5) logger.Warning("Reconnecting to AMQP...") }
// A simplified way to declare and subscribe to an AMQP queue func amqpSubscribe(ch *amqp.Channel, name string, log *blog.AuditLogger) (msgs <-chan amqp.Delivery, err error) { err = ch.ExchangeDeclare( AmqpExchange, AmqpExchangeType, AmqpDurable, AmqpDeleteUnused, AmqpInternal, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not declare exchange: %s", err)) return } q, err := ch.QueueDeclare( name, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not declare queue: %s", err)) return } err = ch.QueueBind( name, name, AmqpExchange, false, nil) if err != nil { log.Crit(fmt.Sprintf("Could not bind queue: %s", err)) return } msgs, err = ch.Consume( q.Name, "", AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not subscribe to queue: %s", err)) return } return }
func setupWFE(c cmd.Config, logger *blog.AuditLogger, stats statsd.Statter) (rpc.RegistrationAuthorityClient, rpc.StorageAuthorityClient, chan *amqp.Error) { ch, err := rpc.AmqpChannel(c) cmd.FailOnError(err, "Could not connect to AMQP") logger.Info(" [!] Connected to AMQP") closeChan := ch.NotifyClose(make(chan *amqp.Error, 1)) raRPC, err := rpc.NewAmqpRPCClient("WFE->RA", c.AMQP.RA.Server, ch, stats) cmd.FailOnError(err, "Unable to create RPC client") saRPC, err := rpc.NewAmqpRPCClient("WFE->SA", c.AMQP.SA.Server, ch, stats) cmd.FailOnError(err, "Unable to create RPC client") rac, err := rpc.NewRegistrationAuthorityClient(raRPC) cmd.FailOnError(err, "Unable to create RA client") sac, err := rpc.NewStorageAuthorityClient(saRPC) cmd.FailOnError(err, "Unable to create SA client") return rac, sac, closeChan }
// A simplified way to declare and subscribe to an AMQP queue func amqpSubscribe(ch *amqp.Channel, name string, consumerName string, log *blog.AuditLogger) (<-chan amqp.Delivery, error) { var err error _, err = ch.QueueDeclare( name, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not declare queue: %s", err)) return nil, err } routingKey := name err = ch.QueueBind( name, routingKey, AmqpExchange, false, nil) if err != nil { log.Crit(fmt.Sprintf("Could not bind to queue [%s]. NOTE: You may need to delete %s to re-trigger the bind attempt after fixing permissions, or manually bind the queue to %s.", name, name, routingKey)) return nil, err } // A consumer name is used so that the specific consumer can be cancelled later // if signalled. If no name is used a UID is used which cannot be retrieved (as // far as I can tell). msgs, err := ch.Consume( name, consumerName, AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not subscribe to queue: %s", err)) return nil, err } return msgs, err }
// A simplified way to declare and subscribe to an AMQP queue func amqpSubscribe(ch *amqp.Channel, name string, log *blog.AuditLogger) (<-chan amqp.Delivery, error) { var err error _, err = ch.QueueDeclare( name, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not declare queue: %s", err)) return nil, err } routingKey := name err = ch.QueueBind( name, routingKey, AmqpExchange, false, nil) if err != nil { log.Crit(fmt.Sprintf("Could not bind to queue [%s]. NOTE: You may need to delete %s to re-trigger the bind attempt after fixing permissions, or manually bind the queue to %s.", name, name, routingKey)) return nil, err } msgs, err := ch.Consume( name, "", AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil) if err != nil { log.Crit(fmt.Sprintf("Could not subscribe to queue: %s", err)) return nil, err } return msgs, err }
func startMonitor(rpcCh *amqp.Channel, logger *blog.AuditLogger, stats statsd.Statter) { ae := analysisengine.NewLoggingAnalysisEngine() // For convenience at the broker, identifiy ourselves by hostname consumerTag, err := os.Hostname() if err != nil { cmd.FailOnError(err, "Could not determine hostname") } _, err = rpcCh.QueueDeclarePassive( QueueName, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { logger.Info(fmt.Sprintf("Queue %s does not exist on AMQP server, attempting to create.", QueueName)) // Attempt to create the Queue if not exists _, err = rpcCh.QueueDeclare( QueueName, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { cmd.FailOnError(err, "Could not declare queue") } routingKey := "#" //wildcard err = rpcCh.QueueBind( QueueName, routingKey, AmqpExchange, false, nil) if err != nil { txt := fmt.Sprintf("Could not bind to queue [%s]. NOTE: You may need to delete %s to re-trigger the bind attempt after fixing permissions, or manually bind the queue to %s.", QueueName, QueueName, routingKey) cmd.FailOnError(err, txt) } } deliveries, err := rpcCh.Consume( QueueName, consumerTag, AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil) if err != nil { cmd.FailOnError(err, "Could not subscribe to queue") } deliveryTimings := make(map[string]time.Time) // Run forever. for d := range deliveries { go timeDelivery(d, stats, deliveryTimings) // Pass each message to the Analysis Engine err = ae.ProcessMessage(d) if err != nil { logger.Alert(fmt.Sprintf("Could not process message: %s", err)) } else { // Only ack the delivery we actually handled (ackMultiple=false) const ackMultiple = false d.Ack(ackMultiple) } } }
func parseLogLine(sa core.StorageAuthority, logger *blog.AuditLogger, line string) (found bool, added bool) { if !strings.Contains(line, "b64der=") { return false, false } derStr := b64derOrphan.FindStringSubmatch(line) if len(derStr) <= 1 { logger.Err(fmt.Sprintf("b64der variable is empty, [%s]", line)) return true, false } der, err := base64.StdEncoding.DecodeString(derStr[1]) if err != nil { logger.Err(fmt.Sprintf("Couldn't decode b64: %s, [%s]", err, line)) return true, false } err = checkDER(sa, der) if err != nil { logger.Err(fmt.Sprintf("%s, [%s]", err, line)) return true, false } // extract the regID regStr := regOrphan.FindStringSubmatch(line) if len(regStr) <= 1 { logger.Err(fmt.Sprintf("regID variable is empty, [%s]", line)) return true, false } regID, err := strconv.Atoi(regStr[1]) if err != nil { logger.Err(fmt.Sprintf("Couldn't parse regID: %s, [%s]", err, line)) return true, false } _, err = sa.AddCertificate(der, int64(regID)) if err != nil { logger.Err(fmt.Sprintf("Failed to store certificate: %s, [%s]", err, line)) return true, false } return true, true }
func startMonitor(rpcCh *amqp.Channel, logger *blog.AuditLogger, stats statsd.Statter) { ae := analysisengine.NewLoggingAnalysisEngine() // For convenience at the broker, identifiy ourselves by hostname consumerTag, err := os.Hostname() if err != nil { cmd.FailOnError(err, "Could not determine hostname") } err = rpcCh.ExchangeDeclare( AmqpExchange, AmqpExchangeType, AmqpDurable, AmqpDeleteUnused, AmqpInternal, AmqpNoWait, nil) if err != nil { cmd.FailOnError(err, "Could not declare exchange") } _, err = rpcCh.QueueDeclare( QueueName, AmqpDurable, AmqpDeleteUnused, AmqpExclusive, AmqpNoWait, nil) if err != nil { cmd.FailOnError(err, "Could not declare queue") } err = rpcCh.QueueBind( QueueName, "#", //wildcard AmqpExchange, false, nil) if err != nil { cmd.FailOnError(err, "Could not bind queue") } deliveries, err := rpcCh.Consume( QueueName, consumerTag, AmqpAutoAck, AmqpExclusive, AmqpNoLocal, AmqpNoWait, nil) if err != nil { cmd.FailOnError(err, "Could not subscribe to queue") } deliveryTimings := make(map[string]time.Time) // Run forever. for d := range deliveries { go timeDelivery(d, stats, deliveryTimings) // Pass each message to the Analysis Engine err = ae.ProcessMessage(d) if err != nil { logger.Alert(fmt.Sprintf("Could not process message: %s", err)) } else { // Only ack the delivery we actually handled (ackMultiple=false) const ackMultiple = false d.Ack(ackMultiple) } } }