Skip to content

Commit

Permalink
test: add Tokenserver integration tests to CI (#1180)
Browse files Browse the repository at this point in the history
Closes #1174
  • Loading branch information
ethowitz authored Dec 8, 2021
1 parent a3d4f09 commit aa18c1a
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ commands:
steps:
- run:
name: cargo build
command: cargo build
command: cargo build --features tokenserver_test_mode
setup-gcp-grpc:
steps:
- run:
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ jsonwebtoken = "7.2.0"

[features]
no_auth = []
tokenserver_test_mode = []

[[bin]]
name = "purge_ttl"
17 changes: 13 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,33 @@ ADD . /app
ENV PATH=$PATH:/root/.cargo/bin
# temp removed --no-install-recommends due to CI docker build issue
RUN apt-get -q update && \
apt-get -q install -y --no-install-recommends default-libmysqlclient-dev cmake golang-go python3-dev python3-pip python3-setuptools && \
apt-get -q install -y --no-install-recommends default-libmysqlclient-dev cmake golang-go python3-dev python3-pip python3-setuptools python3-wheel && \
pip3 install -r requirements.txt && \
rm -rf /var/lib/apt/lists/*

RUN \
cargo --version && \
rustc --version && \
cargo install --path . --locked --root /app && \
cargo install --path . --bin purge_ttl --locked --root /app
cargo install --features tokenserver_test_mode --path . --locked --root /app && \
cargo install --features tokenserver_test_mode --path . --bin purge_ttl --locked --root /app

FROM debian:buster-slim
WORKDIR /app
COPY --from=builder /app/requirements.txt /app
# Due to a build error that occurs with the Python cryptography package, we
# have to set this env var to prevent the cryptography package from building
# with Rust. See this link for more information:
# https://pythonshowcase.com/question/problem-installing-cryptography-on-raspberry-pi
ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
RUN \
groupadd --gid 10001 app && \
useradd --uid 10001 --gid 10001 --home /app --create-home app && \
apt-get -q update && \
apt-get -q install -y build-essential default-libmysqlclient-dev libssl-dev ca-certificates libcurl4 python3-dev python3-pip python3-setuptools curl jq && \
apt-get -q install -y build-essential default-libmysqlclient-dev libssl-dev libffi-dev ca-certificates libcurl4 python3-dev python3-pip python3-setuptools python3-wheel cargo curl jq && \
# The python3-cryptography debian package installs version 2.6.1, but we
# we want to use the version specified in requirements.txt. To do this,
# we have to remove the python3-cryptography package here.
apt-get -q remove -y python3-cryptography && \
pip3 install -r /app/requirements.txt && \
rm -rf /var/lib/apt/lists/*

Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ PATH_TO_GRPC_CERT = ../server-syncstorage/local/lib/python2.7/site-packages/grpc

clippy:
# Matches what's run in circleci
cargo clippy --all --all-targets -- -D warnings
cargo clippy --all --all-targets --all-features -- -D warnings

docker_start_mysql:
docker-compose -f docker-compose.mysql.yaml up -d
Expand All @@ -36,10 +36,10 @@ docker_stop_spanner:
docker-compose -f docker-compose.spanner.yaml down

run:
RUST_LOG=debug RUST_BACKTRACE=full cargo run -- --config config/local.toml
RUST_LOG=debug RUST_BACKTRACE=full cargo run -- --config config/local.toml --features tokenserver_test_mode

run_spanner:
GOOGLE_APPLICATION_CREDENTIALS=$(PATH_TO_SYNC_SPANNER_KEYS) GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=$(PATH_TO_GRPC_CERT) make run

test:
SYNC_DATABASE_URL=$(SYNC_DATABASE_URL) SYNC_TOKENSERVER__DATABASE_URL=$(SYNC_TOKENSERVER__DATABASE_URL) RUST_TEST_THREADS=1 cargo test
SYNC_DATABASE_URL=$(SYNC_DATABASE_URL) SYNC_TOKENSERVER__DATABASE_URL=$(SYNC_TOKENSERVER__DATABASE_URL) RUST_TEST_THREADS=1 cargo test --features tokenserver_test_mode
7 changes: 6 additions & 1 deletion docker-compose.e2e.mysql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ services:
SYNC_HOST: 0.0.0.0
SYNC_MASTER_SECRET: secret0
SYNC_DATABASE_URL: mysql://test:test@sync-db:3306/syncstorage
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3307/tokenserver
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3306/tokenserver
SYNC_TOKENSERVER__ENABLED: "true"
SYNC_TOKENSERVER__FXA_EMAIL_DOMAIN: api-accounts.stage.mozaws.net
SYNC_TOKENSERVER__FXA_METRICS_HASH_SECRET: secret0
SYNC_TOKENSERVER__FXA_OAUTH_SERVER_URL: https://oauth.stage.mozaws.net
TOKENSERVER_HOST: http://localhost:8000
entrypoint: >
/bin/sh -c "
sleep 28; pip3 install -r /app/tools/integration_tests/requirements.txt && python3 /app/tools/integration_tests/run.py 'http://localhost:8000#secret0'
Expand Down
7 changes: 6 additions & 1 deletion docker-compose.e2e.spanner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ services:
SYNC_HOST: 0.0.0.0
SYNC_MASTER_SECRET: secret0
SYNC_DATABASE_URL: spanner://projects/test-project/instances/test-instance/databases/test-database
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3306/tokenserver
SYNC_SPANNER_EMULATOR_HOST: sync-db:9010
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3306/tokenserver
SYNC_TOKENSERVER__ENABLED: "true"
SYNC_TOKENSERVER__FXA_EMAIL_DOMAIN: api-accounts.stage.mozaws.net
SYNC_TOKENSERVER__FXA_METRICS_HASH_SECRET: secret0
SYNC_TOKENSERVER__FXA_OAUTH_SERVER_URL: https://oauth.stage.mozaws.net
TOKENSERVER_HOST: http://localhost:8000
entrypoint: >
/bin/sh -c "
sleep 28; pip3 install -r /app/tools/integration_tests/requirements.txt && python3 /app/tools/integration_tests/run.py 'http://localhost:8000#secret0'
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.mysql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ services:
- tokenserver_db_data:/var/lib/mysql
restart: always
ports:
- "3307"
- "3306"
environment:
#MYSQL_RANDOM_ROOT_PASSWORD: yes
MYSQL_ROOT_PASSWORD: random
Expand All @@ -40,7 +40,7 @@ services:
SYNC_HOST: 0.0.0.0
SYNC_MASTER_SECRET: secret0
SYNC_DATABASE_URL: mysql://test:test@sync-db:3306/syncstorage
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3307/tokenserver
SYNC_TOKENSERVER__DATABASE_URL: mysql://test:test@tokenserver-db:3306/tokenserver

volumes:
sync_db_data:
Expand Down
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# We pin cryptography to 3.4.8 due to a build error that occurs with the
# current version (36.0.0 at the time of this commit). In short, building
# the cryptography package with Rust results in a segfault, so we need to
# set the CRYPTOGRAPHY_DONT_BUILD_RUST env var to force the package to build
# with C instead. This env var is only present in cryptography<3.5.
cryptography==3.4.8
pyfxa==0.7.7
tokenlib==2.0.0
9 changes: 4 additions & 5 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,11 @@ macro_rules! build_app {
.route(web::get().to(handlers::get_bso))
.route(web::put().to(handlers::put_bso)),
)
// XXX: This route will be enabled when we are ready to roll out Tokenserver
// Tokenserver
// .service(
// web::resource("/1.0/{application}/{version}")
// .route(web::get().to(tokenserver::handlers::get_tokenserver_result)),
// )
.service(
web::resource("/1.0/{application}/{version}")
.route(web::get().to(tokenserver::handlers::get_tokenserver_result)),
)
// Dockerflow
// Remember to update .::web::middleware::DOCKER_FLOW_ENDPOINTS
// when applying changes to endpoint names.
Expand Down
4 changes: 2 additions & 2 deletions src/tokenserver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ pub struct ServerState {
impl ServerState {
pub fn from_settings(settings: &Settings) -> Result<Self, ApiError> {
let oauth_verifier: Box<dyn VerifyToken> = if settings.test_mode_enabled {
#[cfg(debug_assertions)]
#[cfg(feature = "tokenserver_test_mode")]
let oauth_verifier = Box::new(TestModeOAuthVerifier);

#[cfg(not(debug_assertions))]
#[cfg(not(feature = "tokenserver_test_mode"))]
let oauth_verifier = Box::new(OAuthVerifier {
fxa_oauth_server_url: settings.fxa_oauth_server_url.clone(),
});
Expand Down
1 change: 1 addition & 0 deletions tools/integration_tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cryptography==3.4.8
hawkauthlib
konfig
mysqlclient
Expand Down
17 changes: 14 additions & 3 deletions tools/integration_tests/run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env python3

import atexit
import os.path
import psutil
import signal
Expand All @@ -9,6 +8,7 @@
from test_storage import TestStorage
from test_support import run_live_functional_tests
import time
from tokenserver.run import run_end_to_end_tests, run_local_tests

DEBUG_BUILD = "target/debug/syncstorage"
RELEASE_BUILD = "/app/bin/syncstorage"
Expand Down Expand Up @@ -50,9 +50,20 @@ def start_server():
os.environ.setdefault("SYNC_MASTER_SECRET", "secret0")
os.environ.setdefault("SYNC_CORS_MAX_AGE", "555")
os.environ.setdefault("SYNC_CORS_ALLOWED_ORIGIN", "localhost")
os.environ['SYNC_TOKENSERVER__TEST_MODE_ENABLED'] = 'true'
the_server_subprocess = start_server()
try:
res = 0
res |= run_live_functional_tests(TestStorage, sys.argv)
res |= run_local_tests()
finally:
terminate_process(the_server_subprocess)

os.environ['SYNC_TOKENSERVER__TEST_MODE_ENABLED'] = 'false'
the_server_subprocess = start_server()
atexit.register(lambda: terminate_process(the_server_subprocess))
res = run_live_functional_tests(TestStorage, sys.argv)
try:
res |= run_end_to_end_tests()
finally:
terminate_process(the_server_subprocess)

sys.exit(res)
5 changes: 2 additions & 3 deletions tools/integration_tests/tokenserver/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def _fxa_metrics_hash(self, value):
hasher.update(value.encode('utf-8'))
return hasher.hexdigest()

def _derive_secret(self, master_secret, node):
def _derive_secret(self, master_secret):
info = "services.mozilla.com/mozsvc/v1/node_secret/%s" % self.NODE_URL
hkdf_params = {
"salt": None,
Expand Down Expand Up @@ -205,8 +205,7 @@ def test_valid_request(self):

signing_secret = binascii.b2a_hex(
self.TOKEN_SIGNING_SECRET.encode("utf-8")).decode()
node_specific_secret = self._derive_secret(signing_secret,
self.NODE_URL)
node_specific_secret = self._derive_secret(signing_secret)
expected_token = tokenlib.make_token(payload_dict,
secret=node_specific_secret)
expected_signature = urlsafe_b64decode(expected_token)[-32:]
Expand Down
4 changes: 2 additions & 2 deletions tools/integration_tests/tokenserver/test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@

class TestCase:
FXA_EMAIL_DOMAIN = 'api-accounts.stage.mozaws.net'
FXA_METRICS_HASH_SECRET = 'secret'
FXA_METRICS_HASH_SECRET = 'secret0'
NODE_ID = 800
NODE_URL = 'https://example.com'
SYNC_1_1_SERVICE_ID = 1
SYNC_1_5_SERVICE_ID = 2
SYNC_1_5_SERVICE_NAME = 'sync-1.5'
TOKEN_SIGNING_SECRET = 'secret'
TOKEN_SIGNING_SECRET = 'secret0'
TOKENSERVER_HOST = os.environ['TOKENSERVER_HOST']

def setUp(self):
Expand Down

0 comments on commit aa18c1a

Please sign in to comment.