1
#pragma once
2

            
3
#include <memory>
4
#include <string>
5

            
6
#include "envoy/buffer/buffer.h"
7
#include "envoy/common/optref.h"
8
#include "envoy/common/time.h"
9
#include "envoy/http/filter.h"
10
#include "envoy/http/header_map.h"
11
#include "envoy/http/metadata_interface.h"
12
#include "envoy/stats/scope.h"
13
#include "envoy/stats/stats_macros.h" // IWYU pragma: keep
14

            
15
#include "source/common/common/logger.h"
16

            
17
#include "absl/strings/string_view.h"
18
#include "absl/types/optional.h"
19
#include "cilium/accesslog.h"
20
#include "cilium/api/accesslog.pb.h"
21
#include "cilium/api/l7policy.pb.h"
22

            
23
namespace Envoy {
24
namespace Cilium {
25

            
26
/**
27
 * All Cilium L7 filter stats. @see stats_macros.h
28
 */
29
// clang-format off
30
#define ALL_CILIUM_STATS(COUNTER)	\
31
113
  COUNTER(access_denied)
32
// clang-format on
33

            
34
/**
35
 * Struct definition for all Cilium L7 filter stats. @see stats_macros.h
36
 */
37
struct FilterStats {
38
  ALL_CILIUM_STATS(GENERATE_COUNTER_STRUCT)
39
};
40

            
41
/**
42
 * Per listener configuration for Cilium HTTP filter. This
43
 * is accessed by multiple working thread instances of the filter.
44
 */
45
class Config : public Logger::Loggable<Logger::Id::filter> {
46
public:
47
  Config(const std::string& access_log_path, const std::string& denied_403_body,
48
         TimeSource& time_source, Stats::Scope& scope, bool is_upstream);
49
  Config(const ::cilium::L7Policy& config, TimeSource& time_source, Stats::Scope& scope,
50
         bool is_upstream);
51

            
52
  void log(AccessLog::Entry&, ::cilium::EntryType);
53

            
54
  TimeSource& time_source_;
55
  FilterStats stats_;
56
  std::string denied_403_body_;
57
  bool is_upstream_;
58

            
59
private:
60
  Cilium::AccessLogSharedPtr access_log_;
61
};
62

            
63
using ConfigSharedPtr = std::shared_ptr<Config>;
64

            
65
// Each request gets their own instance of this filter, and
66
// they can run parallel from multiple worker threads, all accessing
67
// the shared configuration.
68
class AccessFilter : public Http::StreamFilter,
69
                     Logger::Loggable<Logger::Id::filter>,
70
                     public Http::UpstreamCallbacks {
71
public:
72
109
  AccessFilter(ConfigSharedPtr& config) : config_(config) {}
73

            
74
  // UpstreamCallbacks
75
  void onUpstreamConnectionEstablished() override;
76

            
77
  // Http::StreamFilterBase
78
  void onStreamComplete() override;
79
  void onDestroy() override;
80

            
81
  // Http::StreamDecoderFilter
82
  Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers, bool) override;
83
48
  Http::FilterDataStatus decodeData(Buffer::Instance&, bool) override {
84
48
    return Http::FilterDataStatus::Continue;
85
48
  }
86
  Http::FilterTrailersStatus decodeTrailers(Http::RequestTrailerMap&) override {
87
    return Http::FilterTrailersStatus::Continue;
88
  }
89
  void setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callbacks) override;
90

            
91
  // Http::StreamEncoderFilter
92
  Http::Filter1xxHeadersStatus encode1xxHeaders(Http::ResponseHeaderMap&) override {
93
    return Http::Filter1xxHeadersStatus::Continue;
94
  }
95
  Http::FilterHeadersStatus encodeHeaders(Http::ResponseHeaderMap& headers,
96
                                          bool end_stream) override;
97
72
  Http::FilterDataStatus encodeData(Buffer::Instance&, bool) override {
98
72
    return Http::FilterDataStatus::Continue;
99
72
  }
100
  Http::FilterTrailersStatus encodeTrailers(Http::ResponseTrailerMap&) override {
101
    return Http::FilterTrailersStatus::Continue;
102
  }
103
109
  void setEncoderFilterCallbacks(Http::StreamEncoderFilterCallbacks&) override {}
104
  Http::FilterMetadataStatus encodeMetadata(Http::MetadataMap&) override {
105
    return Http::FilterMetadataStatus::Continue;
106
  }
107

            
108
private:
109
  void sendLocalError(absl::string_view details);
110

            
111
  ConfigSharedPtr config_;
112
  Http::StreamDecoderFilterCallbacks* callbacks_ = nullptr;
113

            
114
  AccessLog::Entry* log_entry_ = nullptr;
115

            
116
  OptRef<Http::RequestHeaderMap> latched_headers_;
117
  absl::optional<bool> latched_end_stream_;
118
};
119

            
120
} // namespace Cilium
121
} // namespace Envoy