Skip to content

Commit

Permalink
Dmm/add query to protocol report (#11339)
Browse files Browse the repository at this point in the history
* changelog: Internal, Analytics, Adding facial match issuers query to report
  • Loading branch information
Sgtpluck authored Oct 12, 2024
1 parent aa72cce commit 74b19c4
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 142 deletions.
315 changes: 177 additions & 138 deletions lib/reporting/protocols_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def as_tables
protocols_table,
saml_signature_issues_table,
deprecated_parameters_table,
feature_use_table,
]
end

Expand Down Expand Up @@ -84,110 +85,6 @@ def to_csvs
end
end

def protocol_data
@protocol_data ||= begin
results = cloudwatch_client.fetch(
query: protocol_query,
from: time_range.begin,
to: time_range.end,
)
{
saml: {
request_count: results.
select { |slice| slice['protocol'] == SAML_AUTH_EVENT }.
map { |slice| slice['request_count'].to_i }.
sum,
issuer_count: results.
select { |slice| slice['protocol'] == SAML_AUTH_EVENT }.
map { |slice| slice['issuer'] }.
uniq.
count,
},
oidc: {
request_count: results.
select { |slice| slice['protocol'] == OIDC_AUTH_EVENT }.
map { |slice| slice['request_count'].to_i }.
sum,
issuer_count: results.
select { |slice| slice['protocol'] == OIDC_AUTH_EVENT }.
map { |slice| slice['issuer'] }.
uniq.
count,
},
}
end
end

def saml_signature_data
@saml_signature_data ||= begin
results = cloudwatch_client.fetch(
query: saml_signature_query,
from: time_range.begin,
to: time_range.end,
)
{
unsigned: results.
select { |slice| slice['unsigned_count'].to_i > 0 }.
map { |slice| slice['issuer'] }.
uniq,
invalid_signature: results.
select { |slice| slice['invalid_signature_count'].to_i > 0 }.
map { |slice| slice['issuer'] }.
uniq,
}
end
end

def protocol_query
params = {
event: quote([SAML_AUTH_EVENT, OIDC_AUTH_EVENT]),
}

format(<<~QUERY, params)
fields
name AS protocol,
coalesce(properties.event_properties.service_provider, properties.event_properties.client_id) as issuer
| filter name IN %{event} AND properties.event_properties.success= 1
| stats
count(*) AS request_count
BY
protocol, issuer
QUERY
end

def saml_signature_query
params = {
event: quote([SAML_AUTH_EVENT]),
}

format(<<~QUERY, params)
fields
properties.event_properties.service_provider AS issuer,
properties.event_properties.request_signed = 1 AS signed,
properties.event_properties.request_signed != 1 AS not_signed,
isempty(properties.event_properties.matching_cert_serial) AND signed AS invalid_signature
| filter name IN %{event}
AND properties.event_properties.success = 1
| stats
sum(not_signed) AS unsigned_count,
sum(invalid_signature) AS invalid_signature_count
BY
issuer
| sort
issuer
QUERY
end

def cloudwatch_client
@cloudwatch_client ||= Reporting::CloudwatchClient.new(
num_threads: @threads,
ensure_complete_logs: false,
slice_interval: @slice,
progress: progress?,
logger: verbose? ? Logger.new(STDERR) : nil,
)
end

def overview_table
[
['Report Timeframe', "#{time_range.begin} to #{time_range.end}"],
Expand All @@ -196,22 +93,6 @@ def overview_table
]
end

def saml_count
protocol_data[:saml][:request_count]
end

def oidc_count
protocol_data[:oidc][:request_count]
end

def saml_issuer_count
protocol_data[:saml][:issuer_count]
end

def oidc_issuer_count
protocol_data[:oidc][:issuer_count]
end

def protocols_table
[
['Authentication Protocol', '% of requests', 'Total requests', 'Count of issuers'],
Expand All @@ -232,7 +113,7 @@ def protocols_table

def saml_signature_issues_table
[
['Issue', 'Count of issuers with the issue', 'List of issuers with the issue'],
['Issue', 'Count of issuers', 'List of issuers'],
[
'Not signing SAML authentication requests',
saml_signature_data[:unsigned].length,
Expand All @@ -250,8 +131,8 @@ def deprecated_parameters_table
[
[
'Deprecated Parameter',
'Count of issuers using the parameter',
'List of issuers using the parameter',
'Count of issuers',
'List of issuers',
],
[
'LOA',
Expand All @@ -266,6 +147,37 @@ def deprecated_parameters_table
]
end

def feature_use_table
[
[
'Feature',
'Count of issuers',
'List of issuers',
],
[
'IdV with Facial Match',
facial_match_data.length,
facial_match_data.join(', '),
],
]
end

def saml_count
protocol_data[:saml][:request_count]
end

def oidc_count
protocol_data[:oidc][:request_count]
end

def saml_issuer_count
protocol_data[:saml][:issuer_count]
end

def oidc_issuer_count
protocol_data[:oidc][:issuer_count]
end

def loa_issuers_data
@loa_issuers_data ||= cloudwatch_client.fetch(
query: loa_issuers_query,
Expand All @@ -276,9 +188,83 @@ def loa_issuers_data
uniq
end

def loa_issuers_query
def aal3_issuers_data
@aal3_issuers_data ||= cloudwatch_client.fetch(
query: aal3_issuers_query,
from: time_range.begin,
to: time_range.end,
).
map { |slice| slice['issuer'] }.
uniq
end

def facial_match_data
@facial_match_data ||= cloudwatch_client.fetch(
query: facial_match_issuers_query,
from: time_range.begin,
to: time_range.end,
).
map { |slice| slice['issuer'] }.
uniq
end

def protocol_data
@protocol_data ||= begin
results = cloudwatch_client.fetch(
query: protocol_query,
from: time_range.begin,
to: time_range.end,
)
{
saml: {
request_count: results.
select { |slice| slice['protocol'] == SAML_AUTH_EVENT }.
map { |slice| slice['request_count'].to_i }.
sum,
issuer_count: results.
select { |slice| slice['protocol'] == SAML_AUTH_EVENT }.
map { |slice| slice['issuer'] }.
uniq.
count,
},
oidc: {
request_count: results.
select { |slice| slice['protocol'] == OIDC_AUTH_EVENT }.
map { |slice| slice['request_count'].to_i }.
sum,
issuer_count: results.
select { |slice| slice['protocol'] == OIDC_AUTH_EVENT }.
map { |slice| slice['issuer'] }.
uniq.
count,
},
}
end
end

def saml_signature_data
@saml_signature_data ||= begin
results = cloudwatch_client.fetch(
query: saml_signature_query,
from: time_range.begin,
to: time_range.end,
)
{
unsigned: results.
select { |slice| slice['unsigned_count'].to_i > 0 }.
map { |slice| slice['issuer'] }.
uniq,
invalid_signature: results.
select { |slice| slice['invalid_signature_count'].to_i > 0 }.
map { |slice| slice['issuer'] }.
uniq,
}
end
end

def aal3_issuers_query
params = {
event: quote([SAML_AUTH_EVENT, OIDC_AUTH_EVENT]),
events: quote([SAML_AUTH_EVENT, OIDC_AUTH_EVENT]),
}

format(<<~QUERY, params)
Expand All @@ -287,26 +273,29 @@ def loa_issuers_query
properties.event_properties.acr_values as acr
| parse @message '"authn_context":[*]' as authn
| filter
name IN %{event}
AND (authn like /ns\\/assurance\\/loa/ OR acr like /ns\\/assurance\\/loa/)
AND properties.event_properties.success= 1
name IN %{events}
AND (authn like /aal\\/3/ or acr like /aal\\/3/)
AND properties.event_properties.success = 1
| display issuer
| sort issuer
| dedup issuer
QUERY
end

def aal3_issuers_data
@aal3_issuers_data ||= cloudwatch_client.fetch(
query: aal3_issuers_query,
from: time_range.begin,
to: time_range.end,
).
map { |slice| slice['issuer'] }.
uniq
def facial_match_issuers_query
format(<<~QUERY)
fields
coalesce(properties.event_properties.service_provider,
properties.event_properties.client_id,
properties.service_provider) as issuer
| filter properties.sp_request.facial_match
| display issuer
| sort issuer
| dedup issuer
QUERY
end

def aal3_issuers_query
def loa_issuers_query
params = {
event: quote([SAML_AUTH_EVENT, OIDC_AUTH_EVENT]),
}
Expand All @@ -318,14 +307,64 @@ def aal3_issuers_query
| parse @message '"authn_context":[*]' as authn
| filter
name IN %{event}
AND (authn like /aal\\/3/ or acr like /aal\\/3/)
AND (authn like /ns\\/assurance\\/loa/ OR acr like /ns\\/assurance\\/loa/)
AND properties.event_properties.success= 1
| display issuer
| sort issuer
| dedup issuer
QUERY
end

def protocol_query
params = {
event: quote([SAML_AUTH_EVENT, OIDC_AUTH_EVENT]),
}

format(<<~QUERY, params)
fields
name AS protocol,
coalesce(properties.event_properties.service_provider, properties.event_properties.client_id) as issuer
| filter name IN %{event} AND properties.event_properties.success= 1
| stats
count(*) AS request_count
BY
protocol, issuer
QUERY
end

def saml_signature_query
params = {
events: quote([SAML_AUTH_EVENT]),
}

format(<<~QUERY, params)
fields
properties.event_properties.service_provider AS issuer,
properties.event_properties.request_signed = 1 AS signed,
properties.event_properties.request_signed != 1 AS not_signed,
isempty(properties.event_properties.matching_cert_serial) AND signed AS invalid_signature
| filter name IN %{events}
AND properties.event_properties.success = 1
| stats
sum(not_signed) AS unsigned_count,
sum(invalid_signature) AS invalid_signature_count
BY
issuer
| sort
issuer
QUERY
end

def cloudwatch_client
@cloudwatch_client ||= Reporting::CloudwatchClient.new(
num_threads: @threads,
ensure_complete_logs: false,
slice_interval: @slice,
progress: progress?,
logger: verbose? ? Logger.new(STDERR) : nil,
)
end

def to_percent(numerator, denominator)
(100.0 * numerator / denominator).round(2)
end
Expand Down
Loading

0 comments on commit 74b19c4

Please sign in to comment.