8000 Grafana auth_token MFA by djthread · Pull Request #225 · akoutmos/prom_ex · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Grafana auth_token MFA #225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ erl_crash.dump
# Ignore package tarball (built via "mix hex.build").
prom_ex-*.tar

/.elixir-tools
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Documentation can be found at [https://hexdocs.pm/prom_ex](https://hexdocs.pm/pr

## Supporting PromEx

PromEx has an ambition goal: To provide Prometheus metrics and Grafana dashboards for as many of the libraries in the Elixir ecosystem as possible as well as a framework so that you can manage the lifecycle of your own metrics and dashboards.
PromEx has an ambitious goal: To provide Prometheus metrics and Grafana dashboards for as many of the libraries in the Elixir ecosystem as possible as well as a framework so that you can manage the lifecycle of your own metrics and dashboards.

If you rely on PromEx to monitor your production applications, it would much appreciated if you can give back to the
project in order to help ensure its continued development.
Expand Down Expand Up @@ -93,7 +93,7 @@ project in order to help ensure its continued development.

## Setting Up PromEx

The goal of PromEx is to have metrics set up be as simple and streamlined as possible. In that spirit, all
The goal of PromEx is to make setting up metrics as simple and streamlined as possible. In that spirit, all
that you need to do to start leveraging PromEx along with the built-in plugins is to run the following mix
task (the `YOUR_PROMETHEUS_DATASOURCE_ID` value should align with what is configured in Grafana as the name of the
Prometheus data source):
Expand Down
4 changes: 2 additions & 2 deletions guides/howtos/Writing PromEx Plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ provided to the struct `build` function.

To have your custom plugin expose event based metrics, implement a `event_metrics/1` function and build out a collection
of `Telemetry.Metrics` structs (`distribution`, `counter`, `last_value`, and `sum`). Be sure to look at plugins like
`PromEx.Plugins.Phoenix` for more in depth examples.
`PromEx.Plugins.Phoenix` for more in-depth examples.

```elixir
defmodule MyApp.PromEx.Plugins.MyPhoenix do
Expand Down Expand Up @@ -61,7 +61,7 @@ end
## Adding Polling Metrics

Polling metrics are similar to event metrics in that they require similar fields (`group_name` and `metrics` to be
specific). In addition, the `PromEx.MetricTypes.Polling.build/4` function requires an `measurements_mfa` argument which
specific). In addition, the `PromEx.MetricTypes.Polling.build/4` function requires a `measurements_mfa` argument which
specifies what function will be executed on the polling interval. This function should run `:telemetry.execute/3`
somewhere in its function body. Once that event is executed, the corresponding event in the struct will be triggered and
you will capture the desired data point. The following example from `PromEx.Plugins.Beam` should highlight this concept:
Expand Down
5 changes: 3 additions & 2 deletions lib/prom_ex/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ defmodule PromEx.Config do
via the API.

* `:auth_token` - The auth token that was created in Grafana so that PromEx can upload dashboards
via the API.
via the API. Alternatively, an MFA tuple is allowed. This function must return the auth token string.

* `:upload_dashboards_on_start` - Using the config values that you set in your application config
(`config.exs`, `dev.exs`, `prod.exs`, etc) PromEx will attempt to upload your Dashboards to
Expand Down Expand Up @@ -216,7 +216,8 @@ defmodule PromEx.Config do
config value. When using `:basic` strategy you'll need to provide `:auth_user` and `:auth_password` values.

* `:auth_token` - When using a `:bearer` authentication strategy, this field is required to validate the
incoming request against a valid auth token.
incoming request against a valid auth token. Alternatively, an MFA tuple is allowed. This function must
return the auth token string.

* `:auth_user` - When using a `:basic` authentication strategy, this field is required to validate the
incoming request against a valid user.
Expand Down
8 changes: 8 additions & 0 deletions lib/prom_ex/grafana_client/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ defmodule PromEx.GrafanaClient.Connection do
}
end

def build(finch_process, %{host: host, auth_token: {m, f, a}}) do
%__MODULE__{
finch_process: finch_process,
base_url: normalize_host(host),
authorization: "Bearer #{apply(m, f, a)}"
}
end

Comment on lines +27 to +34

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not accept a function too?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reason is that the mfa is coming in from a config file, and anonymous functions are a no-go there. Probably, an anonymous function could be accepted if passed in another way, but it was out of scope with what I was going for.

def build(finch_process, %{host: host, auth_token: auth_token}) do
%__MODULE__{
finch_process: finch_process,
Expand Down
5 changes: 4 additions & 1 deletion lib/prom_ex/metrics_server/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule PromEx.MetricsServer.Plug do
{:bearer, %{auth_token: auth_token, path: path} = plug_opts}
) do
with ["Bearer " <> req_auth_token] <- get_req_header(conn, "authorization"),
true <- req_auth_token == auth_token do
true <- req_auth_token == resolve_auth_token(auth_token) do
call(conn, {:none, plug_opts})
else
_ ->
Expand Down Expand Up @@ -78,4 +78,7 @@ defmodule PromEx.MetricsServer.Plug do
|> put_resp_content_type("text/plain")
|> send_resp(404, "Not Found")
end

defp resolve_auth_token({m, f, a}), do: apply(m, f, a)
defp resolve_auth_token(token), do: token
end
14 changes: 14 additions & 0 deletions test/prom_ex/grafana_client/connection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ defmodule PromEx.GrafanaClient.ConnectionTest do

alias PromEx.GrafanaClient.Connection

def build_auth_token, do: "made_from_mfa"

describe "build/1" do
test "should properly build a connection struct with provided host, username, and password values" do
finch_name = PromEx.TestFinchName
Expand All @@ -27,5 +29,17 @@ defmodule PromEx.GrafanaClient.ConnectionTest do
authorization: "Bearer " <> ^auth_token
} = Connection.build(finch_name, %{host: base_url, username: nil, password: nil, auth_token: auth_token})
end

test "connection struct with MFA auth_token" do
finch_name = PromEx.TestFinchName
base_url = "http://localhost:3000"
auth_token = {__MODULE__, :build_auth_token, []}

assert %Connection{
finch_process: ^finch_name,
base_url: ^base_url,
authorization: "Bearer made_from_mfa"
} = Connection.build(finch_name, %{host: base_url, username: nil, password: nil, auth_token: auth_token})
end
end
end
24 changes: 24 additions & 0 deletions test/prom_ex/metrics_server/plug_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ defmodule PromEx.MetricsServer.PlugTest do
end
end

def build_auth_token, do: "abcd"

setup_all do
System.put_env("GIT_SHA", "395459c")
System.put_env("GIT_AUTHOR", "Alex")
Expand Down Expand Up @@ -119,6 +121,28 @@ defmodule PromEx.MetricsServer.PlugTest do
assert response.resp_body =~ "Alex"
end

test "should return the metrics for a PromEx instance if the bearer token is MFA" do
opts =
MetricsServer.Plug.init(%{
path: "/metrics",
prom_ex_module: DefaultPromExSetUp,
auth_strategy: :bearer,
auth_token: {__MODULE__, :build_auth_token, []}
})

conn =
:get
|> conn("/metrics")
|> put_req_header("authorization", "Bearer abcd")

response = MetricsServer.Plug.call(conn, opts)

assert response.status == 200
assert response.resp_body =~ "prom_ex_application_primary_info"
assert response.resp_body =~ "395459c"
assert response.resp_body =~ "Alex"
end

test "should return a 401 if the request has an invalid bearer token" do
opts =
MetricsServer.Plug.init(%{
Expand Down
0