Caddy: Add Caddyfile options to configure error log output

Created on 8 Jan 2021  路  7Comments  路  Source: caddyserver/caddy

This issue is a request to add functionality to the Caddyfile to configure the error log output in a similar manner to how the log directive [1] allows this for "access logs". I was motived to open this issue by some of the discussion here: https://github.com/caddyserver/caddy/issues/3744#issuecomment-733288472 which resonates with needs I have run into recently. I haven't been able to find a way to do this so far, which seems to be confirmed by this somewhat recent forum post: https://caddy.community/t/where-to-put-error-log-in-caddyfile/9896/2

The specific situation I've seen motivating this request is that when you have an inbound request with sensitive headers set on it like Cookie or Authorization values that is routed to a reverse_proxy stanza, and if there is an error proxying the request to that backend service, you end up with an error message that looks like the following (I removed some of the default browser headers for simplicity):

2021/01/08 04:21:15.642 ERROR   http.log.error.log0 dial tcp [::1]:8080: connect: connection refused    {"request": {"remote_addr": "127.0.0.1:60809", "proto": "HTTP/2.0", "method": "GET", "host": "localhost", "uri": "/example", "headers": {"Accept": ["*/*"], "Accept-Encoding": ["gzip, deflate, br"], "Accept-Language": ["en-US,en;q=0.9"], "Cookie": ["secret_session_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "localhost"}}, "duration": 0.009280984, "status": 502, "err_id": "5qpcc54u3", "err_trace": "reverseproxy.statusError (reverseproxy.go:783)"}

In this case, it would be a security issue to capture the value of "Cookie": ["secret_session_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] in application logs on the server.

I understand that it may be possible to exclude this type of log with the JSON config [2] but it would be quite convenient to do this with the Caddyfile.

The equivalent functionality in the access logs would be a request>headers>Cookie delete statement similar to the examples for the access log directive: https://caddyserver.com/docs/caddyfile/directives/log#examples

[1] https://caddyserver.com/docs/caddyfile/directives/log
[2] https://caddyserver.com/docs/json/logging/

feature request help wanted

Most helpful comment

I'd recommend a global option syntax very similar to the log directive, but probably with an optional name argument to match how the logs work in JSON config

{
    log [<name>] {
        output <writer_module> ...
        format <encoder_module> ...
        level  <level>
        include <namespaces...>
        exclude <namespaces...>
    }
}

Where if omitted, name would default to default which is... the default logger 馃槢

And log should be able to be specified more than once with different names (similar to servers global directive).

Maybe also a log_sink global option like this:

{
    log_sink <writer_module> ...
}

The Caddyfile adapter should probably warn or error if there's a name conflict between a globally configured logger and a per-site logger (same names), because trying to merge them seems like a terrible idea.

All 7 comments

@mholt thanks for taking a look at this. I may have some time to work on adding something like this, do you have any pointers or thoughts as to what the implementation path might look like?

I'd recommend a global option syntax very similar to the log directive, but probably with an optional name argument to match how the logs work in JSON config

{
    log [<name>] {
        output <writer_module> ...
        format <encoder_module> ...
        level  <level>
        include <namespaces...>
        exclude <namespaces...>
    }
}

Where if omitted, name would default to default which is... the default logger 馃槢

And log should be able to be specified more than once with different names (similar to servers global directive).

Maybe also a log_sink global option like this:

{
    log_sink <writer_module> ...
}

The Caddyfile adapter should probably warn or error if there's a name conflict between a globally configured logger and a per-site logger (same names), because trying to merge them seems like a terrible idea.

Seconding @francislavoie's suggestions.

Would this include errors from reverse_proxy where transport is fastcgi? Still trying to get these logs on a per-host basis.

Would this include errors from reverse_proxy where transport is fastcgi? Still trying to get these logs on a per-host basis.

I think you'll still need to use JSON config for that, because per-host logging requires the logger_names field of HTTP servers. Making that work at the Caddyfile level would be pretty tricky.

But you should be able to configure a logger that includes http.reverse_proxy.transport.fastcgi, I guess.

You would be better served by using jq to transform the logs however you want.

Yeah, I think we already made the mistake of giving users some control over the logs that are emitted; all of that should really be done separate from the web server: you can drop logs on the floor right there or store them, but I made the web server too complicated.

Thanks for the suggestions!

I've got a draft PR open here, let me know your thoughts: https://github.com/caddyserver/caddy/pull/3968

Was this page helpful?
0 / 5 - 0 ratings