Skip to content

Commit

Permalink
Merge pull request #3397 from nulib/3992-superuser-token-query
Browse files Browse the repository at this point in the history
Add GraphQL query for DC API superuser token
  • Loading branch information
mbklein authored Jul 31, 2023
2 parents f4eab4a + ab33022 commit d00f0c2
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 8 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ jobs:
working-directory: app
- name: Install JS dependencies
run: |
npm install --no-fund
npm ci --no-fund
npm list
working-directory: app/assets
- name: Install Lambda dependencies
run: |
for pkg in $(find app/priv/nodejs -maxdepth 2 -name package-lock.json) $(find lambdas -maxdepth 2 -name package-lock.json)
do
cd $(dirname $pkg)
npm install --no-fund
npm ci --no-fund
cd -
done
js-test:
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
POSTGRES_USER: docker
POSTGRES_PASSWORD: d0ck3r
options: >-
--health-cmd pg_isready
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
Expand All @@ -159,7 +159,7 @@ jobs:
ports:
- 9200:9200
localstack:
image: localstack/localstack-pro
image: localstack/localstack-pro:2.1.0
env:
DOCKER_HOST: unix:///var/run/docker.sock
GATEWAY_LISTEN: 0.0.0.0:4566
Expand Down
2 changes: 1 addition & 1 deletion app/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ config :meadow, :extra_mime_types, %{

config :meadow,
dc_api: [
v2: aws_secret("meadow", dig: ["dc_api", "v2"], default: "http://localhost:3000")
v2: aws_secret("meadow", dig: ["dc_api", "v2"])
]

config :hush,
Expand Down
9 changes: 8 additions & 1 deletion app/config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,14 @@ config :ueberauth, Ueberauth,

if prefix = System.get_env("DEV_PREFIX") do
config :meadow,
dc_api: [v2: %{"base_url" => "https://#{prefix}.dev.rdc.library.northwestern.edu:3002"}]
dc_api: [
v2: %{
"api_token_secret" =>
aws_secret("meadow", dig: ["dc_api", "v2", "api_token_secret"], default: "DEV_SECRET"),
"api_token_ttl" => 300,
"base_url" => "https://#{prefix}.dev.rdc.library.northwestern.edu:3002"
}
]
end

config :meadow, :sitemaps,
Expand Down
2 changes: 2 additions & 0 deletions app/config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ config :meadow, Meadow.Repo,
config :meadow,
dc_api: [
v2: %{
"api_token_secret" => "TEST_SECRET",
"api_token_ttl" => 300,
"base_url" => "http://dcapi-test.northwestern.edu"
}
]
Expand Down
20 changes: 20 additions & 0 deletions app/lib/meadow_web/resolvers/helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ defmodule MeadowWeb.Resolvers.Helpers do
alias Meadow.Config
alias Meadow.Utils.AWS

def get_dc_api_token(_, _args, _) do
with api_config <- Application.get_env(:meadow, :dc_api)[:v2],
issued_at <- DateTime.utc_now(),
ttl <- Map.get(api_config, "api_token_ttl", 300),
expires_at <- DateTime.add(issued_at, ttl) do
token = %{
iss: "meadow",
exp: DateTime.to_unix(expires_at),
iat: DateTime.to_unix(issued_at),
entitlements: [],
isLoggedIn: false,
isSuperUser: true
}

{:ok, token} = :jwt.encode("HS256", token, api_config["api_token_secret"])

{:ok, %{token: token, expires: expires_at}}
end
end

def get_presigned_url(_, %{upload_type: "preservation_check"} = params, _) do
with {:ok, url} <- AWS.presigned_url(Config.preservation_check_bucket(), params) do
{:ok, %{url: url}}
Expand Down
5 changes: 5 additions & 0 deletions app/lib/meadow_web/schema/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ defmodule MeadowWeb.Schema do
value(:desc)
end

object :api_token do
field :token, non_null(:string)
field :expires, non_null(:datetime)
end

object :url do
field :url, non_null(:string)
end
Expand Down
6 changes: 6 additions & 0 deletions app/lib/meadow_web/schema/types/helper_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ defmodule MeadowWeb.Schema.HelperTypes do
resolve(&Resolvers.Helpers.get_presigned_url/3)
end

@desc "Get a signed superuser DC API token"
field :dc_api_token, :api_token do
middleware(Middleware.Authenticate)
resolve(&Resolvers.Helpers.get_dc_api_token/3)
end

@desc "Get work archiver endpoint"
field :work_archiver_endpoint, :url do
middleware(Middleware.Authenticate)
Expand Down
3 changes: 2 additions & 1 deletion app/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Code.require_file("lib/env.ex")
defmodule Meadow.MixProject do
use Mix.Project

@app_version "8.0.6"
@app_version "8.1.0"

def project do
[
Expand Down Expand Up @@ -82,6 +82,7 @@ defmodule Meadow.MixProject do
{:hush_aws_secrets_manager, "~> 0.1"},
{:inflex, "~> 2.1.0"},
{:jason, "~> 1.0"},
{:jwt, "~> 0.1.11"},
{:logger_file_backend, "~> 0.0.11"},
{:mox, "~> 1.0", only: :test},
{:nimble_csv, "~> 1.2.0"},
Expand Down
3 changes: 3 additions & 0 deletions app/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"atomic_map": {:hex, :atomic_map, "0.9.3", "3c7f1302e0590164732d08ca999708efbb2cd768abf2911cf140280ce2dc499d", [:mix], [], "hexpm", "c237babf301bd2435bd85b96cffc973022b4cbb7721537059ee0dd3bb74938d2"},
"authoritex": {:hex, :authoritex, "1.0.2", "356353f3271090f7fb6f7880e02fbfadfcb52a057cad2d20db495631f8d1809d", [:mix], [{:httpoison, "~> 1.8.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:httpoison_retry, "~> 1.1.0", [hex: :httpoison_retry, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: false]}], "hexpm", "d680eb60c454adf213cd498718ca4f21052212523edf12208dee4291724a1f98"},
"aws_signature": {:hex, :aws_signature, "0.3.1", "67f369094cbd55ffa2bbd8cc713ede14b195fcfb45c86665cd7c5ad010276148", [:rebar3], [], "hexpm", "50fc4dc1d1f7c2d0a8c63f455b3c66ecd74c1cf4c915c768a636f9227704a674"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
"briefly": {:hex, :briefly, "0.4.1", "c90c0511e64bde1fe8da7e244e14acf5bc78c3f6d033db778205e1fa2feafa5c", [:mix], [], "hexpm", "fc0cafcd19c4ed0d0906ae5cf627cc6ce76b8652a160c6bde0ab9d77304ebb0a"},
"broadway": {:hex, :broadway, "1.0.7", "7808f9e3eb6f53ca6d060f0f9d61012dd8feb0d7a82e62d087dd517b9b66fa53", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.3.7 or ~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e76cfb0a7d64176c387b8b1ddbfb023e2ee8a63e92f43664d78e6d5d0b1177c6"},
"broadway_dashboard": {:hex, :broadway_dashboard, "0.3.0", "912da4c459baed0cd9c356bffa1645d82f3b3fc72b23cc52b2429eef317952b2", [:mix], [{:broadway, "~> 1.0", [hex: :broadway, repo: "hexpm", optional: false]}, {:phoenix_live_dashboard, "~> 0.5.1 or ~> 0.6.0 or ~> 0.7.0", [hex: :phoenix_live_dashboard, repo: "hexpm", optional: false]}], "hexpm", "2f48848fa388edce1f07fdcf0eae7b4fcab1244a82ffcf758120fd9ca875e4a6"},
Expand Down Expand Up @@ -54,7 +55,9 @@
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"},
"jumper": {:hex, :jumper, "1.0.1", "3c00542ef1a83532b72269fab9f0f0c82bf23a35e27d278bfd9ed0865cecabff", [:mix], [], "hexpm", "318c59078ac220e966d27af3646026db9b5a5e6703cb2aa3e26bcfaba65b7433"},
"jwt": {:hex, :jwt, "0.1.11", "4f18896c4a182530ed445312c45ac353d801fbdfd54f538910370e9cf12687cf", [:rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}, {:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "b483fbb786d1bd050b3c551d323112d604e5b0f9cf9dc5671adeec462c2e36bb"},
"logger_file_backend": {:hex, :logger_file_backend, "0.0.13", "df07b14970e9ac1f57362985d76e6f24e3e1ab05c248055b7d223976881977c2", [:mix], [], "hexpm", "71a453a7e6e899ae4549fb147b1c6621f4233f8f48f58ca10a64ec67b6c50018"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
Expand Down
35 changes: 35 additions & 0 deletions app/test/meadow_web/schema/query/api_token_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule MeadowWeb.Schema.Query.ApiTokenTest do
use MeadowWeb.ConnCase, async: true
use Wormwood.GQLCase

set_gql(
MeadowWeb.Schema,
"""
query {
dcApiToken {
expires
token
}
}
"""
)

test "should return a signed API token" do
assert {:ok, %{data: data}} =
query_gql(
variables: %{},
context: gql_context()
)

assert {:ok, expires} =
get_in(data, ["dcApiToken", "expires"]) |> NaiveDateTime.from_iso8601()

assert get_in(data, ["dcApiToken", "token"]) |> is_binary()

assert_in_delta(
NaiveDateTime.diff(expires, NaiveDateTime.utc_now(), :second),
300,
2
)
end
end
10 changes: 9 additions & 1 deletion infrastructure/deploy/secrets.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
data "aws_cloudformation_stack" "dc_api" {
name = var.dcapi_stack_name
}

locals {
api_token_secret = data.aws_cloudformation_stack.dc_api.parameters.ApiTokenSecret

config_secrets = {
buckets = {
ingest = aws_s3_bucket.meadow_ingest.bucket
Expand All @@ -24,7 +30,9 @@ locals {

dc_api = {
v2 = {
base_url = var.dc_api_v2_base
api_token_secret = local.api_token_secret
api_token_ttl = 300
base_url = var.dc_api_v2_base
}
}

Expand Down
5 changes: 5 additions & 0 deletions infrastructure/deploy/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ variable "db_size" {
default = 5
}

variable "dcapi_stack_name" {
type = string
default = "dc-api-v2"
}

variable "certificate_name" {
type = string
default = "*"
Expand Down

0 comments on commit d00f0c2

Please sign in to comment.