Skip to content

Commit

Permalink
Merge branch 'main' into integ-logging
Browse files Browse the repository at this point in the history
  • Loading branch information
jmayclin authored Sep 18, 2024
2 parents 9fedcbf + 1c948da commit 31e9bfb
Show file tree
Hide file tree
Showing 195 changed files with 1,044 additions and 496 deletions.
126 changes: 126 additions & 0 deletions .github/bin/criterion_to_cloudwatch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# A copy of the License is located at
#
# http://aws.amazon.com/apache2.0
#
# or in the "license" file accompanying this file. This file is distributed
# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
#

import argparse
import json
from typing import Tuple
from collections.abc import Generator
import boto3


class CriterionResult:
def __init__(self, json_obj: dict):
self._json_obj: dict = json_obj

@property
def _group_and_category(self) -> Tuple[str, str]:
id_ = self._json_obj["id"]

# The id is made up of the bench group and the category, separated by a /.
# For example: handshake-ecdsa384/s2n-tls
id_split = id_.split("/")
assert len(id_split) == 2

group = id_split[0]
category = id_split[1]

return group, category

@property
def group(self) -> str:
group, category = self._group_and_category
return group

@property
def category(self) -> str:
group, category = self._group_and_category
return category

@property
def mean_us(self) -> float:
mean = self._json_obj["mean"]

unit = mean["unit"]
assert unit == "ns"

# CloudWatch doesn't support nanoseconds, so the units are converted to microseconds.
estimate_ns = mean["estimate"]
estimate_us = estimate_ns / 1_000

return estimate_us


class CriterionReader:
def __init__(self, criterion_output_path: str):
self.criterion_output_path: str = criterion_output_path

def read_bench_results(self) -> Generator[CriterionResult, None, None]:
with open(self.criterion_output_path, 'r') as output:
for line in output.readlines():
obj = json.loads(line)

# Skip criterion output that isn't describing a benchmarking result.
if obj.get("reason") != "benchmark-complete":
continue

yield CriterionResult(obj)


if __name__ == '__main__':
parser = argparse.ArgumentParser(
prog="criterion_to_cloudwatch",
description="Emits CloudWatch metrics from criterion output.",
)
parser.add_argument(
"--criterion_output_path",
required=True,
help="File containing criterion json output. Generated with cargo-criterion by specifying the "
"`--message-format json` option.",
)
parser.add_argument(
"--namespace",
required=True,
help="CloudWatch namespace to emit metrics to (e.g. s2n-tls-bench).",
)
parser.add_argument(
"--platform",
required=True,
help="Specifies the platform dimension of the CloudWatch metrics (e.g. Ubuntu24-x86).",
)
args = parser.parse_args()

cloudwatch = boto3.client("cloudwatch")

reader = CriterionReader(args.criterion_output_path)
for result in reader.read_bench_results():
print(f"Emitting {args.namespace} - {result.group}/{result.category} for {args.platform}: {result.mean_us}")

cloudwatch.put_metric_data(
Namespace=args.namespace,
MetricData=[{
"MetricName": result.group,
"Dimensions": [
{
"Name": "Category",
"Value": result.category,
},
{
"Name": "Platform",
"Value": args.platform,
},
],
"Value": result.mean_us,
"Unit": "Microseconds",
}],
)
48 changes: 48 additions & 0 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Benchmarking

on:
push:
branches: [main]
schedule:
# run the job daily at midnight
- cron: "0 0 * * *"

jobs:
bench:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: '3.x'

- name: Install dependencies
run: |
rustup toolchain install stable
rustup override set stable
cargo install cargo-criterion
pip3 install "boto3[crt]"
- name: Generate
working-directory: bindings/rust
run: ./generate.sh --skip-tests

- name: Benchmark
working-directory: bindings/rust/bench
run: cargo criterion --message-format json > criterion_output.log

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2

- name: Emit CloudWatch metrics
run: |
python3 .github/bin/criterion_to_cloudwatch.py \
--criterion_output_path bindings/rust/bench/criterion_output.log \
--namespace s2n-tls-bench \
--platform ${{ runner.os }}-${{ runner.arch }}
67 changes: 67 additions & 0 deletions .github/workflows/seccomp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: seccomp
on:
pull_request:
branches: [main]
merge_group:
types: [checks_requested]
branches: [main]

jobs:
ubuntu:
runs-on: ubuntu-latest
steps:
- name: install dependencies
run: |
sudo apt update
sudo apt install cmake
# For default libcrypto
sudo apt install libssl-dev
# For seccomp
sudo apt install libseccomp-dev
# For aws-lc
sudo apt install clang golang
- name: checkout s2n-tls
uses: actions/checkout@v4

- name: checkout aws-lc
uses: actions/checkout@v4
with:
repository: aws/aws-lc
path: awslc

- name: build awslc
# See https://github.com/aws/aws-lc/blob/main/BUILDING.md#building
working-directory: awslc
run: |
cmake -B build
make -C build
cmake --install build --prefix install
- name: seccomp with default libcrypto
# TODO: There are still issues with openssl running with seccomp.
# Disable for now.
if: false
run: |
cmake -Bbuild \
-DSECCOMP=1 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=install
cmake --build build -j $(nproc)
CTEST_PARALLEL_LEVEL=$(nproc) ctest --test-dir build
cmake --install build
./build/bin/s2nc localhost 8000 | grep "libcrypto" | grep -v "AWS-LC"
rm -rf build
- name: seccomp with aws-lc
run: |
cmake -Bbuild \
-DSECCOMP=1 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=awslc/install \
-DCMAKE_INSTALL_PREFIX=install
cmake --build build -j $(nproc)
CTEST_PARALLEL_LEVEL=$(nproc) ctest --test-dir build
cmake --install build
./build/bin/s2nc localhost 8000 | grep "libcrypto" | grep "AWS-LC"
rm -rf build
94 changes: 91 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ option(S2N_INSTALL_S2NC_S2ND "Install the binaries s2nc and s2nd" OFF)
option(S2N_USE_CRYPTO_SHARED_LIBS "For S2N to use shared libs in Findcrypto" OFF)
option(TSAN "Enable ThreadSanitizer to test thread safety" OFF)
option(ASAN "Enable AddressSanitizer to test memory safety" OFF)
option(SECCOMP "Link with seccomp and run seccomp tests" OFF)

# Turn BUILD_TESTING=ON by default
include(CTest)
Expand Down Expand Up @@ -145,7 +146,7 @@ elseif (UNSAFE_TREAT_WARNINGS_AS_ERRORS)
target_compile_options(${PROJECT_NAME} PRIVATE -Werror )
endif ()

if(BUILD_TESTING AND BUILD_SHARED_LIBS)
if(BUILD_TESTING AND BUILD_SHARED_LIBS OR S2N_FUZZ_TEST)
target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=default)
else()
target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden -DS2N_EXPORTS)
Expand Down Expand Up @@ -183,8 +184,9 @@ if(NO_STACK_PROTECTOR)
target_compile_options(${PROJECT_NAME} PRIVATE -Wstack-protector -fstack-protector-all)
endif()

if(S2N_UNSAFE_FUZZING_MODE)
target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize-coverage=trace-pc-guard -fsanitize=address,undefined,leak -fuse-ld=gold -DS2N_ADDRESS_SANITIZER=1)
if(S2N_FUZZ_TEST)
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=fuzzer-no-link,leak)
target_link_libraries(${PROJECT_NAME} PUBLIC -fsanitize=fuzzer-no-link,leak)
endif()

if(TSAN)
Expand Down Expand Up @@ -451,6 +453,11 @@ if (BUILD_TESTING)
target_include_directories(testss2n PUBLIC tests)
target_compile_options(testss2n PRIVATE -std=gnu99)
target_link_libraries(testss2n PUBLIC ${PROJECT_NAME})
if (SECCOMP)
message(STATUS "Linking tests with seccomp")
target_link_libraries(testss2n PRIVATE seccomp)
target_compile_definitions(testss2n PRIVATE SECCOMP)
endif()

if (S2N_INTERN_LIBCRYPTO)
# if libcrypto was interned, rewrite libcrypto symbols so use of internal functions will link correctly
Expand Down Expand Up @@ -587,6 +594,87 @@ if (BUILD_TESTING)
set_property(TEST ${test_target} PROPERTY TIMEOUT 7200)
endforeach()
endif()

if(S2N_FUZZ_TEST)
message(STATUS "Fuzz build enabled")
set(SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/runFuzzTest.sh")
file(GLOB FUZZ_TEST_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/*.c")

file(GLOB TESTLIB_SRC "tests/testlib/*.c")
file(GLOB TESTLIB_HEADERS "tests/testlib/*.h" "tests/s2n_test.h")

add_library(fuzztest SHARED ${TESTLIB_HEADERS} ${TESTLIB_SRC})
target_include_directories(fuzztest PUBLIC tests)
target_link_libraries(fuzztest PUBLIC ${PROJECT_NAME})

# Set default values for fuzzing if not defined
if(NOT DEFINED FUZZ_TIMEOUT_SEC)
set(FUZZ_TIMEOUT_SEC 60)
endif()

if(NOT DEFINED CORPUS_UPLOAD_LOC)
set(CORPUS_UPLOAD_LOC "none")
endif()

if(NOT DEFINED ARTIFACT_UPLOAD_LOC)
set(ARTIFACT_UPLOAD_LOC "none")
endif()

if(NOT DEFINED FUZZ_TESTS)
set(FUZZ_TESTS "${TESTS}")
endif()

# Build LD_PRELOAD shared libraries
set(LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/LD_PRELOAD)
file(GLOB LIBRARY_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/LD_PRELOAD/*.c")
foreach(SRC ${LIBRARY_SRCS})
get_filename_component(LIB_NAME ${SRC} NAME_WE)
add_library(${LIB_NAME} SHARED ${SRC})
target_include_directories(${LIB_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/api
)
# Set the output directory and remove the default "lib" prefix
set_target_properties(${LIB_NAME} PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_DIRECTORY}
)
target_compile_options(${LIB_NAME} PRIVATE
-fPIC
)
endforeach()

set(CMAKE_C_COMPILER clang)

foreach(src ${FUZZ_TEST_SRCS})
get_filename_component(TEST_NAME ${src} NAME_WE)

add_executable(${TEST_NAME} ${src})
target_include_directories(${TEST_NAME} PRIVATE ./)

target_compile_options(${TEST_NAME} PRIVATE
-g -Wno-unknown-pragmas -Wno-unused-result
)
target_link_libraries(${TEST_NAME} PRIVATE
fuzztest
-fsanitize=fuzzer -lstdc++
)

# Set the output directory for the fuzzing binaries
set(FUZZ_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz")
set_target_properties(${TEST_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${FUZZ_BIN_DIR}
)

add_test(NAME ${TEST_NAME}
COMMAND ${CMAKE_COMMAND} -E env
DYLD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/lib:${CMAKE_CURRENT_BINARY_DIR}/tests/testlib:${CMAKE_CURRENT_SOURCE_DIR}/libcrypto-root/lib:$ENV{DYLD_LIBRARY_PATH}
LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}/lib:${CMAKE_CURRENT_BINARY_DIR}/tests/testlib:${CMAKE_CURRENT_SOURCE_DIR}/libcrypto-root/lib:$ENV{LD_LIBRARY_PATH}
bash ${SCRIPT_PATH} ${TEST_NAME} ${FUZZ_TIMEOUT_SEC} ${CORPUS_UPLOAD_LOC} ${ARTIFACT_UPLOAD_LOC}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz)
set_property(TEST ${TEST_NAME} PROPERTY LABELS "fuzz")
endforeach()
endif()
endif()

#install the s2n files
Expand Down
4 changes: 2 additions & 2 deletions bindings/rust/s2n-tls-hyper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ publish = false
default = []

[dependencies]
s2n-tls = { version = "=0.3.1", path = "../s2n-tls" }
s2n-tls-tokio = { version = "=0.3.1", path = "../s2n-tls-tokio" }
s2n-tls = { version = "=0.3.2", path = "../s2n-tls" }
s2n-tls-tokio = { version = "=0.3.2", path = "../s2n-tls-tokio" }
hyper = { version = "1" }
hyper-util = { version = "0.1", features = ["client-legacy", "tokio", "http1"] }
tower-service = { version = "0.3" }
Expand Down
Loading

0 comments on commit 31e9bfb

Please sign in to comment.