feat: OpenSSL crypto support for kms/crate/utils with full FIPS support (#115)
* Rebase grnx-fix-fips from develop
* Pull Cargo.lock from develop
* fips: fixed test_password_wrap_import and opened issue #124
* fips: generated non-deprecated pkcs12 certificates
* test: fix old uid size in test covercrypt import key
* fix: revert some unneeded changes
* fixbug: padded be bytes key conversions
* fix: typos
* ci: rewrite tests in container
* Revert "ci: rewrite tests in container"
This reverts commit 7adb273660
.
* ci: redis hostname 0.0.0.0
* docs: wrote docs on fips algorithms
* ci: use host addresses for docker containers use
* ci: merge ubuntu workflows
* fixbug: padded remnant conversions with âd_be_bytes() on other files
* fix: given mutability in function call in pad_be_bytes()
* ci: re-add test var. env. for Google CSE
* ci: re-add test var. env. for Google CSE
* bugfix: to_u32_digits() created little-endian u32 from big endian bytes.
* fix: Remove bootstrap server and enclave (#122)
* Remove bootstrap server
* Remove enclave-related stuff
* Apply suggestions from code review
Co-authored-by: heavenboy <49846064+heavenboy8@users.noreply.github.com>
* Update crate/server/README.md
Co-authored-by: heavenboy <49846064+heavenboy8@users.noreply.github.com>
* Renaming verify_cert into client_cert
* Add KMS supervisor conf and instructions
* remove acme dep
---------
Co-authored-by: heavenboy <49846064+heavenboy8@users.noreply.github.com>
Co-authored-by: Sébastien Lambert <sebastien.lambert@cosmian.com>
* comments: added hunk of comments on bugfix for to_u32_digits()
* fix: remove useless deps from Cargo.toml
* bugfix: padded in kmip_data_structure an EC private key from BigUint to bytes
* fix: remove openssl from cli
---------
Co-authored-by: Bruno Grieder <bruno.grieder@cosmian.com>
Co-authored-by: Manuthor <manu.coste@gmail.com>
Co-authored-by: Thibs <ThibsG@users.noreply.github.com>
Co-authored-by: heavenboy <49846064+heavenboy8@users.noreply.github.com>
Co-authored-by: Sébastien Lambert <sebastien.lambert@cosmian.com>
This commit is contained in:
parent
36bd22ef97
commit
3ad1bc7217
136 changed files with 2722 additions and 5058 deletions
130
.github/workflows/build_all.yml
vendored
Normal file
130
.github/workflows/build_all.yml
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
---
|
||||
name: Build all
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
toolchain:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
OPENSSL_DIR: /tmp/openssl_fips
|
||||
|
||||
jobs:
|
||||
centos7:
|
||||
uses: ./.github/workflows/build_centos7.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
archive-name: centos7
|
||||
commands: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
|
||||
cargo test --release -- --nocapture
|
||||
cargo test --release --bins -- --nocapture
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
fips-centos7:
|
||||
uses: ./.github/workflows/build_centos7.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
archive-name: fips_centos7
|
||||
commands: |
|
||||
cargo build --release --features fips --bin ckms
|
||||
cargo build --release --features fips --bin cosmian_kms_server
|
||||
|
||||
cargo test --release --features fips -- --nocapture
|
||||
cargo test --release --features fips --bins -- --nocapture
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
ubuntu-20:
|
||||
uses: ./.github/workflows/build_generic_linux.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-20.04
|
||||
archive-name: ubuntu_20_04
|
||||
commands: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
|
||||
cargo test --release -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
cargo test --release --bins -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
fips-ubuntu-20:
|
||||
uses: ./.github/workflows/build_generic_linux.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-20.04
|
||||
archive-name: fips_ubuntu_20_04
|
||||
commands: |
|
||||
cargo build --release --features fips --bin ckms
|
||||
cargo build --release --features fips --bin cosmian_kms_server
|
||||
|
||||
cargo test --release --features fips -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
cargo test --release --features fips --bins -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
ubuntu-22:
|
||||
uses: ./.github/workflows/build_generic_linux.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-22.04
|
||||
archive-name: ubuntu_22_04
|
||||
commands: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
|
||||
cargo test --release -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
cargo test --release --bins -- --nocapture --skip test_mysql --skip test_pgsql --skip test_redis
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
windows:
|
||||
uses: ./.github/workflows/build_generic_linux.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-20.04
|
||||
archive-name: windows
|
||||
commands: |
|
||||
sudo apt-get install --no-install-recommends -qq libclang-dev gcc-mingw-w64-x86-64
|
||||
rustup target add x86_64-pc-windows-gnu
|
||||
|
||||
rm -rf /tmp/openssl_fips
|
||||
mkdir -p /tmp/openssl_fips
|
||||
bash ./scripts/local_ossl_instl.sh /tmp/openssl_fips cross-compile-windows
|
||||
|
||||
cargo build --release --bin ckms --target x86_64-pc-windows-gnu
|
||||
cargo build --release --bin cosmian_kms_server --target x86_64-pc-windows-gnu
|
||||
artifacts: |
|
||||
target/x86_64-pc-windows-gnu/release/ckms.exe
|
||||
target/x86_64-pc-windows-gnu/release/cosmian_kms_server.exe
|
||||
|
||||
mac:
|
||||
uses: ./.github/workflows/build_generic_linux.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: macos-12
|
||||
archive-name: macos
|
||||
commands: |
|
||||
rustup target add x86_64-apple-darwin
|
||||
cargo build --release --bin ckms --target x86_64-apple-darwin
|
||||
cargo build --release --bin cosmian_kms_server --target x86_64-apple-darwin
|
||||
artifacts: |
|
||||
target/x86_64-apple-darwin/release/ckms
|
||||
target/x86_64-apple-darwin/release/cosmian_kms_server
|
148
.github/workflows/build_centos7.yml
vendored
Normal file
148
.github/workflows/build_centos7.yml
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
---
|
||||
name: Centos
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
toolchain:
|
||||
required: true
|
||||
type: string
|
||||
commands:
|
||||
required: true
|
||||
type: string
|
||||
archive-name:
|
||||
required: true
|
||||
type: string
|
||||
artifacts:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
OPENSSL_DIR: /tmp/openssl_fips
|
||||
|
||||
jobs:
|
||||
centos7-tests:
|
||||
services:
|
||||
# Label used to access the service container
|
||||
postgres:
|
||||
# Docker Hub image
|
||||
image: postgres
|
||||
# Provide the password for postgres
|
||||
env:
|
||||
POSTGRES_USER: kms
|
||||
PGUSER: kms
|
||||
POSTGRES_PASSWORD: kms
|
||||
POSTGRES_DB: kms
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
mariadb:
|
||||
image: mariadb
|
||||
env:
|
||||
MYSQL_DATABASE: kms
|
||||
MYSQL_ROOT_PASSWORD: kms
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
name: ${{ inputs.archive-name }}
|
||||
container:
|
||||
image: iyxd/centos7-rust
|
||||
|
||||
steps:
|
||||
- name: Display cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# `curl` in Centos 7 is too old (7.29) regarding
|
||||
# what `dtolnay/rust-toolchain` needs because it is
|
||||
# using `--retry-connrefused` option (curl 7.52).
|
||||
# Drop this when moving to Centos 8
|
||||
- name: Update curl for Centos 7
|
||||
run: |
|
||||
curl --version
|
||||
chmod +x ./scripts/centos_install_curl.sh
|
||||
./scripts/centos_install_curl.sh
|
||||
curl --version
|
||||
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Centos 7 prerequisites
|
||||
run: |
|
||||
set -x
|
||||
export PERL_MM_USE_DEFAULT=1
|
||||
|
||||
yum -y groupinstall "Development Tools"
|
||||
yum -y install perl-IPC-Cmd perl-Digest-SHA1 perl-CPAN perl-devel
|
||||
|
||||
- name: install cpanm and SHA module
|
||||
uses: perl-actions/install-with-cpanm@stable
|
||||
with:
|
||||
install: |
|
||||
Digest::SHA
|
||||
sudo: false
|
||||
|
||||
- name: Local OpenSSL FIPS Install
|
||||
run: |
|
||||
bash ./scripts/local_ossl_instl.sh ${{ env.OPENSSL_DIR }}
|
||||
|
||||
- name: Pre-cleanup
|
||||
run: |
|
||||
set -x
|
||||
rm -rf /tmp/sqlite-data /tmp/tmp.json
|
||||
|
||||
- name: Build and tests in release
|
||||
run: |
|
||||
set -x
|
||||
${{ inputs.commands }}
|
||||
env:
|
||||
OPENSSL_DIR: ${{ env.OPENSSL_DIR }}
|
||||
RUST_LOG: cosmian_kms_server=trace
|
||||
|
||||
POSTGRES_USER: kms
|
||||
PGUSER: kms
|
||||
POSTGRES_PASSWORD: kms
|
||||
POSTGRES_DB: kms
|
||||
KMS_POSTGRES_URL: postgres://kms:kms@postgres/kms
|
||||
|
||||
MYSQL_DATABASE: kms
|
||||
MYSQL_ROOT_PASSWORD: kms
|
||||
KMS_MYSQL_URL: mysql://root:kms@mariadb/kms
|
||||
|
||||
KMS_ENCLAVE_DIR_PATH: data/public
|
||||
KMS_SQLITE_PATH: data/shared
|
||||
KMS_CERTBOT_SSL_PATH: data/private
|
||||
|
||||
REDIS_HOST: redis
|
||||
|
||||
# Google variables
|
||||
TEST_GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_ID }}
|
||||
TEST_GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_SECRET }}
|
||||
TEST_GOOGLE_OAUTH_REFRESH_TOKEN: ${{ secrets.TEST_GOOGLE_OAUTH_REFRESH_TOKEN }}
|
||||
|
||||
# Speeds up Ristretto 25519 multiplication x 2
|
||||
RUSTFLAGS: --cfg curve25519_dalek_backend="simd" -C target-cpu=native
|
||||
|
||||
- name: Upload KMS for Centos7
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.archive-name }}
|
||||
path: ${{ inputs.artifacts }}
|
||||
retention-days: 1
|
||||
if-no-files-found: error
|
|
@ -10,7 +10,7 @@ env:
|
|||
|
||||
jobs:
|
||||
pyo3:
|
||||
uses: ./.github/workflows/python_build.yml
|
||||
uses: ./.github/workflows/maturin.yml
|
||||
with:
|
||||
toolchain: nightly-2023-08-17
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
name: KMS build
|
||||
name: KMS build for MacOS and Windows runner - no docker
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
@ -20,9 +20,12 @@ on:
|
|||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
OPENSSL_DIR: /tmp/openssl_fips
|
||||
|
||||
jobs:
|
||||
kms-build:
|
||||
name: Build ${{ inputs.archive-name }}
|
||||
name: ${{ inputs.archive-name }}
|
||||
runs-on: ${{ inputs.distribution }}
|
||||
steps:
|
||||
- name: Display cpuinfo
|
||||
|
@ -51,12 +54,23 @@ jobs:
|
|||
toolchain: ${{ inputs.toolchain }}
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Local OpenSSL FIPS Install
|
||||
if: steps.cargo_cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
bash ./scripts/local_ossl_instl.sh ${{ env.OPENSSL_DIR }}
|
||||
|
||||
- name: Build
|
||||
if: steps.cargo_cache.outputs.cache-hit != 'true'
|
||||
run: ${{ inputs.commands }}
|
||||
env:
|
||||
# Speeds up Ristretto 25519 multiplication x 2
|
||||
RUSTFLAGS: --cfg curve25519_dalek_backend="simd" -C target-cpu=native
|
||||
OPENSSL_DIR: ${{ env.OPENSSL_DIR }}
|
||||
# Google variables
|
||||
TEST_GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_ID }}
|
||||
TEST_GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_SECRET }}
|
||||
TEST_GOOGLE_OAUTH_REFRESH_TOKEN: ${{ secrets.TEST_GOOGLE_OAUTH_REFRESH_TOKEN }}
|
||||
|
||||
|
||||
- name: Upload KMS for ${{ inputs.distribution }}
|
||||
if: steps.cargo_cache.outputs.cache-hit != 'true'
|
224
.github/workflows/cargo_tests.yml
vendored
224
.github/workflows/cargo_tests.yml
vendored
|
@ -1,224 +0,0 @@
|
|||
---
|
||||
name: Cargo tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
toolchain:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
# Cleanup task is required for self-hosted runner since docker user is root and all files in target folder are under root permissions
|
||||
cleanup:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Chown user
|
||||
run: |
|
||||
echo "USER: $USER"
|
||||
echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE"
|
||||
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
|
||||
|
||||
kms-tests:
|
||||
needs: cleanup
|
||||
services:
|
||||
# Label used to access the service container
|
||||
postgres:
|
||||
# Docker Hub image
|
||||
image: postgres
|
||||
# Provide the password for postgres
|
||||
env:
|
||||
POSTGRES_USER: kms
|
||||
PGUSER: kms
|
||||
POSTGRES_PASSWORD: kms
|
||||
POSTGRES_DB: kms
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
mariadb:
|
||||
image: mariadb
|
||||
env:
|
||||
MYSQL_DATABASE: kms
|
||||
MYSQL_ROOT_PASSWORD: kms
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
# runs-on: [self-hosted, not-sgx] # currently not needed.
|
||||
container:
|
||||
image: iyxd/centos7-rust
|
||||
|
||||
steps:
|
||||
- name: Display cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# `curl` in Centos 7 is too old (7.29) regarding
|
||||
# what `dtolnay/rust-toolchain` needs because it is
|
||||
# using `--retry-connrefused` option (curl 7.52).
|
||||
# Drop this when moving to Centos 8
|
||||
- name: Update curl for Centos 7
|
||||
run: |
|
||||
curl --version
|
||||
chmod +x ./scripts/centos_install_curl.sh
|
||||
./scripts/centos_install_curl.sh
|
||||
curl --version
|
||||
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Centos 7 prerequisites
|
||||
run: |
|
||||
yum -y groupinstall "Development Tools"
|
||||
yum -y install openssl openssl-devel
|
||||
|
||||
- name: Tests in debug
|
||||
run: |
|
||||
rm -rf /tmp/sqlite-data /tmp/tmp.json
|
||||
export RUST_BACKTRACE=1 CARGO_INCREMENTAL=0
|
||||
cargo build --no-default-features
|
||||
cargo test --no-default-features -- --nocapture
|
||||
cargo test --bins -- --nocapture
|
||||
env:
|
||||
POSTGRES_USER: kms
|
||||
PGUSER: kms
|
||||
POSTGRES_PASSWORD: kms
|
||||
POSTGRES_DB: kms
|
||||
KMS_POSTGRES_URL: postgres://kms:kms@postgres/kms
|
||||
|
||||
MYSQL_DATABASE: kms
|
||||
MYSQL_ROOT_PASSWORD: kms
|
||||
KMS_MYSQL_URL: mysql://root:kms@mariadb/kms
|
||||
|
||||
KMS_ENCLAVE_DIR_PATH: data/public
|
||||
KMS_SQLITE_PATH: data/shared
|
||||
KMS_CERTBOT_SSL_PATH: data/private
|
||||
|
||||
REDIS_HOST: redis
|
||||
|
||||
TEST_GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_ID }}
|
||||
TEST_GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_SECRET }}
|
||||
TEST_GOOGLE_OAUTH_REFRESH_TOKEN: ${{ secrets.TEST_GOOGLE_OAUTH_REFRESH_TOKEN }}
|
||||
|
||||
kms-centos7:
|
||||
needs: cleanup
|
||||
runs-on: ubuntu-22.04
|
||||
# runs-on: [self-hosted, not-sgx] # currently not needed.
|
||||
container:
|
||||
image: iyxd/centos7-rust
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# `curl` in Centos 7 is too old (7.29) regarding
|
||||
# what `dtolnay/rust-toolchain` needs because it is
|
||||
# using `--retry-connrefused` option (curl 7.52).
|
||||
# Drop this when moving to Centos 8
|
||||
- name: Update curl for Centos 7
|
||||
run: |
|
||||
curl --version
|
||||
chmod +x ./scripts/centos_install_curl.sh
|
||||
./scripts/centos_install_curl.sh
|
||||
curl --version
|
||||
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Centos 7 prerequisites
|
||||
run: |
|
||||
yum -y groupinstall "Development Tools"
|
||||
yum -y install openssl openssl-devel
|
||||
|
||||
- name: Build with Auth0 feature
|
||||
run: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
env:
|
||||
# Speeds up Ristretto 25519 multiplication x 2
|
||||
RUSTFLAGS: --cfg curve25519_dalek_backend="simd" -C target-cpu=native
|
||||
|
||||
- name: Upload KMS for Centos7
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kms_centos7
|
||||
path: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
retention-days: 1
|
||||
if-no-files-found: error
|
||||
|
||||
kms-ubuntu-20:
|
||||
needs: cleanup
|
||||
uses: ./.github/workflows/cargo_build.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-20.04
|
||||
archive-name: kms_ubuntu_20_04
|
||||
commands: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
kms-ubuntu-22:
|
||||
needs: cleanup
|
||||
uses: ./.github/workflows/cargo_build.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-22.04
|
||||
archive-name: kms_ubuntu_22_04
|
||||
commands: |
|
||||
cargo build --release --bin ckms
|
||||
cargo build --release --bin cosmian_kms_server
|
||||
artifacts: |
|
||||
target/release/ckms
|
||||
target/release/cosmian_kms_server
|
||||
|
||||
kms-windows:
|
||||
needs: cleanup
|
||||
uses: ./.github/workflows/cargo_build.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: ubuntu-20.04
|
||||
archive-name: kms_windows
|
||||
commands: |
|
||||
sudo apt-get install --no-install-recommends -qq libclang-dev gcc-mingw-w64-x86-64
|
||||
rustup target add x86_64-pc-windows-gnu
|
||||
cargo build --release --bin ckms --target x86_64-pc-windows-gnu
|
||||
cargo build --release --bin cosmian_kms_server --target x86_64-pc-windows-gnu
|
||||
artifacts: |
|
||||
target/x86_64-pc-windows-gnu/release/ckms.exe
|
||||
target/x86_64-pc-windows-gnu/release/cosmian_kms_server.exe
|
||||
|
||||
kms-mac:
|
||||
needs: cleanup
|
||||
uses: ./.github/workflows/cargo_build.yml
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
distribution: macos-12
|
||||
archive-name: kms_macos
|
||||
commands: |
|
||||
rustup target add x86_64-apple-darwin
|
||||
cargo build --release --bin ckms --target x86_64-apple-darwin
|
||||
cargo build --release --bin cosmian_kms_server --target x86_64-apple-darwin
|
||||
artifacts: |
|
||||
target/x86_64-apple-darwin/release/ckms
|
||||
target/x86_64-apple-darwin/release/cosmian_kms_server
|
|
@ -8,6 +8,9 @@ on:
|
|||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
OPENSSL_DIR: /tmp/openssl_fips
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-22.04
|
||||
|
@ -28,6 +31,10 @@ jobs:
|
|||
key: ${{ runner.os }}-cargo-lint-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cargo-lint-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Local OpenSSL FIPS Install
|
||||
run: |
|
||||
bash ./scripts/local_ossl_instl.sh ${{ env.OPENSSL_DIR }}
|
||||
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
|
@ -39,3 +46,5 @@ jobs:
|
|||
|
||||
- name: Static analysis
|
||||
run: cargo clippy --workspace --all-targets --all-features --release -- -D warnings
|
||||
env:
|
||||
OPENSSL_DIR: ${{ env.OPENSSL_DIR }}
|
123
.github/workflows/docker_kms_sgx.yml
vendored
123
.github/workflows/docker_kms_sgx.yml
vendored
|
@ -1,123 +0,0 @@
|
|||
---
|
||||
name: Docker KMS SGX
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
REGISTRY_IMAGE: ghcr.io/cosmian/enclave-kms-insecure
|
||||
KMS_USE_BOOTSTRAP_SERVER: true
|
||||
KMS_USE_CERTBOT: true
|
||||
KMS_CERTBOT_HOSTNAME: kms.sgx.ci.cosmian.dev
|
||||
KMS_CERTBOT_EMAIL: tech@cosmian.com
|
||||
KMS_CERTBOT_USE_TEE_KEY: abcdef0123456789
|
||||
TESTS_CONTAINER_NETWORK: # dynamic variable retrieved during the tests
|
||||
|
||||
jobs:
|
||||
build-push-image-and-tests:
|
||||
runs-on: [self-hosted, sgx]
|
||||
container:
|
||||
image: ubuntu:22.04
|
||||
ports:
|
||||
- 4431:443
|
||||
- 8081:80
|
||||
|
||||
steps:
|
||||
- name: Install tools
|
||||
run: |
|
||||
apt update
|
||||
apt install --no-install-recommends -qq -y \
|
||||
docker.io \
|
||||
curl \
|
||||
ca-certificates \
|
||||
build-essential
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Following job from `docker_kms_sgx_tests.yml` will overwrite
|
||||
# this file, but for unknown reason sometimes permissions are denied to do so.
|
||||
- name: Fix permissions on JSON file
|
||||
run: chmod o+w ./ci/sgx/kms-test-ci.json
|
||||
|
||||
- name: Login to GitHub Packages
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY_IMAGE }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
# Specify staging features to use Let's Encrypt staging environment in order to be able to request more than 5 certificates by week
|
||||
# Documentation : https://letsencrypt.org/docs/duplicate-certificate-limit/
|
||||
- name: Build and tag docker container
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
file: ./ci/sgx/Dockerfile.sgx
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
network: host
|
||||
build-args: |
|
||||
FEATURES=--features staging
|
||||
|
||||
#########
|
||||
# Tests #
|
||||
#########
|
||||
- name: Retrieve current Docker network
|
||||
run: echo "TESTS_CONTAINER_NETWORK=$(docker network ls |grep github_network | head -n1 | cut -d' ' -f1)" >> $GITHUB_ENV
|
||||
|
||||
- name: Docker start container
|
||||
run: |
|
||||
docker run \
|
||||
--pull always \
|
||||
--network "${{ env.TESTS_CONTAINER_NETWORK }}" \
|
||||
--device /dev/sgx_enclave \
|
||||
--device /dev/sgx_provision \
|
||||
-e KMS_USE_BOOTSTRAP_SERVER="${{ env.KMS_USE_BOOTSTRAP_SERVER }}" \
|
||||
-e KMS_USE_CERTBOT="${{ env.KMS_USE_CERTBOT }}" \
|
||||
-e KMS_CERTBOT_HOSTNAME="${{ env.KMS_CERTBOT_HOSTNAME }}" \
|
||||
-e KMS_CERTBOT_EMAIL="${{ env.KMS_CERTBOT_EMAIL }}" \
|
||||
-e KMS_CERTBOT_USE_TEE_KEY="${{ env.KMS_CERTBOT_USE_TEE_KEY }}" \
|
||||
-v /var/run/aesmd:/var/run/aesmd/ \
|
||||
-v /opt/cosmian-internal:/opt/cosmian-internal \
|
||||
-p 80:80 \
|
||||
-p 9998:9998 \
|
||||
-d --rm --name enclave-kms-insecure ghcr.io/cosmian/enclave-kms-insecure:${{ steps.meta.outputs.version }}
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install ckms
|
||||
run: cargo install --locked --path crate/cli
|
||||
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
KMS_CLI_CONF=$PWD/ci/sgx/kms-test-ci.json ckms bootstrap-start --sqlite-path private_data/ --database-type sqlite
|
||||
sleep 20
|
||||
|
||||
- name: Verify
|
||||
run: KMS_CLI_CONF=$PWD/ci/sgx/kms-test-ci.json ckms verify
|
||||
|
||||
- name: Symmetric key create
|
||||
run: KMS_CLI_CONF=$PWD/ci/sgx/kms-test-ci.json ckms sym keys create
|
||||
|
||||
- name: Docker stop container
|
||||
if: success() || failure()
|
||||
run: |
|
||||
docker logs --tail 20 enclave-kms-insecure
|
||||
docker stop enclave-kms-insecure
|
9
.github/workflows/github_cache_cleanup.yml
vendored
Normal file
9
.github/workflows/github_cache_cleanup.yml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: Github cache cleanup
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
uses: Cosmian/reusable_workflows/.github/workflows/cleanup_cache.yml@develop
|
||||
secrets: inherit
|
|
@ -22,12 +22,12 @@ jobs:
|
|||
uses: Cosmian/reusable_workflows/.github/workflows/cargo-udeps.yml@develop
|
||||
|
||||
cargo-lint:
|
||||
uses: ./.github/workflows/lint.yml
|
||||
uses: ./.github/workflows/clippy.yml
|
||||
with:
|
||||
toolchain: nightly-2023-08-17
|
||||
|
||||
cargo-tests:
|
||||
uses: ./.github/workflows/cargo_tests.yml
|
||||
build:
|
||||
uses: ./.github/workflows/build_all.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
toolchain: nightly-2023-08-17
|
||||
|
@ -38,7 +38,7 @@ jobs:
|
|||
toolchain: nightly-2023-08-17
|
||||
|
||||
python_and_docker:
|
||||
uses: ./.github/workflows/python_and_docker.yml
|
||||
uses: ./.github/workflows/build_docker_image.yml
|
||||
|
||||
##############################################################################
|
||||
### Releases
|
||||
|
@ -50,9 +50,8 @@ jobs:
|
|||
- cargo-udeps
|
||||
- cargo-lint
|
||||
- cargo-doc
|
||||
- cargo-tests
|
||||
- build
|
||||
- python_and_docker
|
||||
# - sgx_docker # do not depend on this for releases
|
||||
runs-on: [self-hosted, not-sgx]
|
||||
strategy:
|
||||
fail-fast: false
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,7 +10,6 @@ data/keys
|
|||
**/data/public
|
||||
**/data/shared
|
||||
crate/cli/*.sqlite
|
||||
sgx/kms-test-*.json
|
||||
.DS_Store
|
||||
.idea/
|
||||
rustc-ice*.txt
|
||||
|
|
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -3,8 +3,6 @@
|
|||
"actix",
|
||||
"ascii",
|
||||
"canonicalize",
|
||||
"certbot",
|
||||
"Certbot",
|
||||
"chacha",
|
||||
"ciphertext",
|
||||
"ciphertexts",
|
||||
|
@ -26,7 +24,6 @@
|
|||
"keypair",
|
||||
"kmip",
|
||||
"KMIP",
|
||||
"libsgx",
|
||||
"mozilla",
|
||||
"mysql",
|
||||
"nginx",
|
||||
|
@ -68,5 +65,6 @@
|
|||
"rust-analyzer.check.command": "clippy",
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "ms-python.autopep8"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.showUnlinkedFileNotification": false
|
||||
}
|
||||
|
|
435
Cargo.lock
generated
435
Cargo.lock
generated
|
@ -2,21 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "acme-lib"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/Cosmian/acme-lib?branch=master#12e2831797394778ff1136216a459fb3a2f6087f"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"openssl",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"time 0.1.45",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-codec"
|
||||
version = "0.5.1"
|
||||
|
@ -49,29 +34,6 @@ dependencies = [
|
|||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-files"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d832782fac6ca7369a70c9ee9a20554623c5e51c76e190ad151780ebea1cf689"
|
||||
dependencies = [
|
||||
"actix-http",
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"askama_escape",
|
||||
"bitflags 1.3.2",
|
||||
"bytes",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"http-range",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.4.0"
|
||||
|
@ -138,44 +100,6 @@ dependencies = [
|
|||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-multipart"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b960e2aea75f49c8f069108063d12a48d329fc8b60b786dfc7552a9d5918d2d"
|
||||
dependencies = [
|
||||
"actix-multipart-derive",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"bytes",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"httparse",
|
||||
"local-waker",
|
||||
"log",
|
||||
"memchr",
|
||||
"mime",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-multipart-derive"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a0a77f836d869f700e5b47ac7c3c8b9c8bc82e4aec861954c6198abee3ebd4d"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"parse-size",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-router"
|
||||
version = "0.5.1"
|
||||
|
@ -313,7 +237,7 @@ dependencies = [
|
|||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2 0.5.5",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -501,21 +425,6 @@ dependencies = [
|
|||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_escape"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||
|
||||
[[package]]
|
||||
name = "asn1"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae3ecbce89a22627b5e8e6e11d69715617138290289e385cde773b1fe50befdb"
|
||||
dependencies = [
|
||||
"asn1_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs"
|
||||
version = "0.5.2"
|
||||
|
@ -529,7 +438,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -555,17 +464,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1_derive"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "861af988fac460ac69a09f41e6217a8fb9178797b76fcc9478444be6a59be19c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "2.0.12"
|
||||
|
@ -649,6 +547,12 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base58"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
|
@ -673,21 +577,6 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -994,12 +883,6 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codicon"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12170080f3533d6f09a19f81596f836854d0fa4867dc32c8172b8474b4e9de61"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.6"
|
||||
|
@ -1043,7 +926,7 @@ dependencies = [
|
|||
"rand",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -1147,6 +1030,7 @@ dependencies = [
|
|||
name = "cosmian_kmip"
|
||||
version = "4.10.1"
|
||||
dependencies = [
|
||||
"base58",
|
||||
"bitflags 2.4.1",
|
||||
"chrono",
|
||||
"cloudproof",
|
||||
|
@ -1157,9 +1041,10 @@ dependencies = [
|
|||
"pyo3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha3",
|
||||
"strum",
|
||||
"thiserror",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"zeroize",
|
||||
|
@ -1183,20 +1068,17 @@ dependencies = [
|
|||
"cosmian_kms_utils",
|
||||
"cosmian_logger",
|
||||
"der",
|
||||
"hex",
|
||||
"oauth2",
|
||||
"openssl",
|
||||
"pem",
|
||||
"predicates",
|
||||
"rand",
|
||||
"ratls",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum",
|
||||
"tee_attestation",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
@ -1217,16 +1099,11 @@ dependencies = [
|
|||
"http",
|
||||
"josekit",
|
||||
"log",
|
||||
"openssl",
|
||||
"ratls",
|
||||
"reqwest",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tee_attestation",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"url",
|
||||
"webpki-roots 0.22.6",
|
||||
]
|
||||
|
@ -1251,12 +1128,9 @@ dependencies = [
|
|||
name = "cosmian_kms_server"
|
||||
version = "4.10.1"
|
||||
dependencies = [
|
||||
"acme-lib",
|
||||
"actix-cors",
|
||||
"actix-files",
|
||||
"actix-http",
|
||||
"actix-identity",
|
||||
"actix-multipart",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
|
@ -1281,16 +1155,14 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"mime",
|
||||
"openssl",
|
||||
"ratls",
|
||||
"rawsql",
|
||||
"redis",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tee_attestation",
|
||||
"thiserror",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
|
@ -1470,41 +1342,6 @@ dependencies = [
|
|||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.5.0"
|
||||
|
@ -1656,7 +1493,6 @@ dependencies = [
|
|||
"digest",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"sha2",
|
||||
"signature",
|
||||
"spki",
|
||||
]
|
||||
|
@ -1984,7 +1820,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
@ -2126,12 +1962,6 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
|
@ -2224,12 +2054,6 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
|
@ -2272,12 +2096,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iocuddle"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8972d5be69940353d5347a1344cb375d9b457d6809b428b05bb1ca2fb9ce007"
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.9.0"
|
||||
|
@ -2343,7 +2161,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2540,7 +2358,7 @@ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
|
@ -2768,15 +2586,6 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-src"
|
||||
version = "111.28.0+1.1.1w"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ce95ee1f6f999dfb95b8afd43ebe442758ea2104d1ccb99a94c30db22ae701f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.91"
|
||||
|
@ -2785,7 +2594,6 @@ checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac"
|
|||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"openssl-src",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
@ -2873,12 +2681,6 @@ dependencies = [
|
|||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-size"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae"
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.5.0"
|
||||
|
@ -3239,27 +3041,6 @@ dependencies = [
|
|||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ratls"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Cosmian/tee-tools?branch=get_quote#9085550a81f35c1a869e5d70bf43864225c5bae4"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"bincode",
|
||||
"const-oid",
|
||||
"der",
|
||||
"ecdsa",
|
||||
"p256",
|
||||
"rand_chacha",
|
||||
"rustls",
|
||||
"sha2",
|
||||
"spki",
|
||||
"tee_attestation",
|
||||
"thiserror",
|
||||
"x509-cert",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawsql"
|
||||
version = "0.1.1"
|
||||
|
@ -3564,26 +3345,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
|
||||
dependencies = [
|
||||
"scroll_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll_derive"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scrypt"
|
||||
version = "0.11.0"
|
||||
|
@ -3657,24 +3418,6 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-big-array"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
|
@ -3708,15 +3451,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
|
@ -3729,82 +3463,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sev"
|
||||
version = "1.2.1"
|
||||
source = "git+https://github.com/virtee/sev?rev=a6d6568c96a7a5d6c55d10228a54cda5f3c32e44#a6d6568c96a7a5d6c55d10228a54cda5f3c32e44"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitfield",
|
||||
"bitflags 1.3.2",
|
||||
"codicon",
|
||||
"dirs",
|
||||
"hex",
|
||||
"iocuddle",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"openssl",
|
||||
"serde",
|
||||
"serde-big-array",
|
||||
"serde_bytes",
|
||||
"static_assertions",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sev_quote"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Cosmian/tee-tools?branch=get_quote#9085550a81f35c1a869e5d70bf43864225c5bae4"
|
||||
dependencies = [
|
||||
"asn1",
|
||||
"asn1-rs",
|
||||
"bincode",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"log",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"sev",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sgx_pck_extension"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/Cosmian/tee-tools?branch=get_quote#9085550a81f35c1a869e5d70bf43864225c5bae4"
|
||||
dependencies = [
|
||||
"asn1",
|
||||
"asn1-rs",
|
||||
"thiserror",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sgx_quote"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/Cosmian/tee-tools?branch=get_quote#9085550a81f35c1a869e5d70bf43864225c5bae4"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"elliptic-curve",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"log",
|
||||
"p256",
|
||||
"reqwest",
|
||||
"rsa",
|
||||
"scroll",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sgx_pck_extension",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"urlencoding",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
@ -4158,12 +3816,6 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.25.0"
|
||||
|
@ -4253,17 +3905,6 @@ version = "0.12.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||
|
||||
[[package]]
|
||||
name = "tee_attestation"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/Cosmian/tee-tools?branch=get_quote#9085550a81f35c1a869e5d70bf43864225c5bae4"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"sev_quote",
|
||||
"sgx_quote",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.1"
|
||||
|
@ -4322,17 +3963,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.30"
|
||||
|
@ -4642,22 +4272,6 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7830e33f6e25723d41a63f77e434159dad02919f18f55a512b5f16f3b1d77138"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"flate2",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-webpki",
|
||||
"url",
|
||||
"webpki-roots 0.25.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -4683,7 +4297,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4722,12 +4335,6 @@ dependencies = [
|
|||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -4999,23 +4606,23 @@ dependencies = [
|
|||
"ring 0.16.20",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time 0.3.30",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.26"
|
||||
version = "0.7.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0"
|
||||
checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.26"
|
||||
version = "0.7.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
|
||||
checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -53,14 +53,6 @@ dependencies = [
|
|||
"ci-rust-tests",
|
||||
]
|
||||
|
||||
[tasks.ci-enclave-tests]
|
||||
category = "dev"
|
||||
description = "Run Rust tests"
|
||||
script = '''
|
||||
cargo build --bin ckms
|
||||
cargo test --features staging --no-default-features -p kms
|
||||
'''
|
||||
|
||||
#
|
||||
# Local tests
|
||||
#
|
||||
|
|
16
README.md
16
README.md
|
@ -31,8 +31,6 @@ And also some libraries:
|
|||
**Please refer to the README of the inner directories to have more
|
||||
information.**
|
||||
|
||||
The `sgx` directory contains all the requirements to run the KMS inside an Intel SGX enclave.
|
||||
|
||||
You can build a docker containing the KMS server as follow:
|
||||
|
||||
```sh
|
||||
|
@ -58,3 +56,17 @@ cargo test --no-default-features
|
|||
## Releases
|
||||
|
||||
All releases can be found in the public URL [package.cosmian.com](https://package.cosmian.com/kms/).
|
||||
|
||||
## Setup as a `Supervisor` service
|
||||
|
||||
Copy the binary `target/release/cosmian_kms` to the remote machine folder according to [cosmian_kms.ini](./resources/supervisor/cosmian_kms.ini) statement (ie: `/usr/sbin/cosmian_kms`).
|
||||
|
||||
Copy the [cosmian_kms.ini](./resources/supervisor/cosmian_kms.ini) config file as `/etc/supervisord.d/cosmian_kms.ini` in the remote machine.
|
||||
|
||||
Run:
|
||||
|
||||
```console
|
||||
supervisorctl reload
|
||||
supervisorctl start cosmian_kms
|
||||
supervisorctl status cosmian_kms
|
||||
```
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
FROM ubuntu:22.04 as minimal-sgx
|
||||
|
||||
USER root
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TS=Etc/UTC
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
RUN echo 'APT::Install-Suggests "0";' >> /etc/apt/apt.conf.d/00-docker
|
||||
RUN echo 'APT::Install-Recommends "0";' >> /etc/apt/apt.conf.d/00-docker
|
||||
RUN apt-get update && apt-get install --no-install-recommends -qq -y \
|
||||
build-essential \
|
||||
protobuf-compiler \
|
||||
libprotobuf-dev \
|
||||
libprotobuf-c-dev \
|
||||
python3 \
|
||||
gnupg \
|
||||
ca-certificates \
|
||||
curl \
|
||||
libsodium-dev \
|
||||
tzdata \
|
||||
&& apt-get -y -q upgrade \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Gramine APT repository
|
||||
RUN curl -fsSLo /usr/share/keyrings/gramine-keyring.gpg https://packages.gramineproject.io/gramine-keyring.gpg && \
|
||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gramine-keyring.gpg] https://packages.gramineproject.io/ jammy main" \
|
||||
| tee /etc/apt/sources.list.d/gramine.list
|
||||
|
||||
# Intel SGX APT repository
|
||||
RUN curl -fsSLo /usr/share/keyrings/intel-sgx-deb.asc https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key && \
|
||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx-deb.asc] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" \
|
||||
| tee /etc/apt/sources.list.d/intel-sgx.list
|
||||
|
||||
# Install Intel SGX dependencies and Gramine
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libsgx-launch \
|
||||
libsgx-urts \
|
||||
libsgx-quote-ex \
|
||||
libsgx-epid \
|
||||
libsgx-dcap-ql \
|
||||
libsgx-dcap-quote-verify \
|
||||
linux-base-sgx \
|
||||
libsgx-dcap-default-qpl \
|
||||
sgx-aesm-service \
|
||||
libsgx-aesm-quote-ex-plugin \
|
||||
gramine && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# SGX SDK is installed in /opt/intel directory.
|
||||
WORKDIR /opt/intel
|
||||
|
||||
ARG SGX_SDK_VERSION=2.21
|
||||
ARG SGX_SDK_INSTALLER=sgx_linux_x64_sdk_2.21.100.1.bin
|
||||
|
||||
# Install SGX SDK
|
||||
RUN curl -fsSLo $SGX_SDK_INSTALLER https://download.01.org/intel-sgx/sgx-linux/$SGX_SDK_VERSION/distro/ubuntu22.04-server/$SGX_SDK_INSTALLER \
|
||||
&& chmod +x $SGX_SDK_INSTALLER \
|
||||
&& echo "yes" | ./$SGX_SDK_INSTALLER \
|
||||
&& rm $SGX_SDK_INSTALLER
|
||||
|
||||
#
|
||||
# Minimal Rust image
|
||||
#
|
||||
FROM ubuntu:22.04 as minimal-rust
|
||||
|
||||
USER root
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TS=Etc/UTC
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends -qq -y \
|
||||
curl \
|
||||
build-essential \
|
||||
libssl-dev \
|
||||
ca-certificates \
|
||||
libclang-dev \
|
||||
libsodium-dev \
|
||||
pkg-config \
|
||||
&& apt-get -y -q upgrade \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
|
||||
COPY . /root
|
||||
|
||||
ARG FEATURES
|
||||
|
||||
RUN /root/.cargo/bin/cargo build --release --no-default-features ${FEATURES}
|
||||
|
||||
#
|
||||
# Minimal kms
|
||||
#
|
||||
FROM minimal-sgx as kms
|
||||
|
||||
USER root
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TS=Etc/UTC
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
ENV KMS_USE_BOOTSTRAP_SERVER =$KMS_USE_BOOTSTRAP_SERVER
|
||||
ENV KMS_USE_CERTBOT=$KMS_USE_CERTBOT
|
||||
ENV KMS_CERTBOT_HOSTNAME=$KMS_CERTBOT_HOSTNAME
|
||||
ENV KMS_CERTBOT_EMAIL=$KMS_CERTBOT_EMAIL
|
||||
ENV KMS_CERTBOT_USE_TEE_KEY=$KMS_CERTBOT_USE_TEE_KEY
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
RUN mkdir -p scripts
|
||||
# private_data, public_data and shared_data are supposed to be given as parameters of the docker run
|
||||
|
||||
COPY --from=minimal-rust /root/target/release/cosmian_kms_server scripts/server
|
||||
|
||||
COPY ci/sgx/build_and_run.sh ci/sgx/Makefile ci/sgx/kms.manifest.template /root/
|
||||
|
||||
ENTRYPOINT ["./build_and_run.sh"]
|
|
@ -1,47 +0,0 @@
|
|||
ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine)
|
||||
SGX_SIGNER_KEY ?= /opt/cosmian-internal/cosmian-signer-key.pem
|
||||
SGX_SIGNER_PUBLIC_KEY = cosmian-signer-key.pub
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
GRAMINE_LOG_LEVEL = debug
|
||||
# can also use "all" for having something like `strace`
|
||||
else
|
||||
GRAMINE_LOG_LEVEL = error
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: kms.manifest
|
||||
ifeq ($(SGX),1)
|
||||
all: kms.manifest.sgx kms.sig
|
||||
endif
|
||||
|
||||
kms.manifest: kms.manifest.template
|
||||
gramine-manifest \
|
||||
-Dlog_level=$(GRAMINE_LOG_LEVEL) \
|
||||
-Darch_libdir=$(ARCH_LIBDIR) \
|
||||
-Dentrypoint_abs="$(PWD)/scripts" \
|
||||
-Dentrypoint="/scripts" \
|
||||
-Dsgx_signer_public_key=$(SGX_SIGNER_PUBLIC_KEY) \
|
||||
-Dkms_use_bootstrap_server=$(KMS_USE_BOOTSTRAP_SERVER) \
|
||||
-Dkms_use_cerbot=$(KMS_USE_CERTBOT) \
|
||||
-Dkms_cerbot_hostname=$(KMS_CERTBOT_HOSTNAME) \
|
||||
-Dkms_cerbot_email=$(KMS_CERTBOT_EMAIL) \
|
||||
-Dkms_cerbot_use_tee_key=$(KMS_CERTBOT_USE_TEE_KEY) \
|
||||
-Dkms_domain="$(KMS_DOMAIN)" \
|
||||
$< >$@
|
||||
|
||||
kms.manifest.sgx: kms.manifest
|
||||
gramine-sgx-sign \
|
||||
--key $(SGX_SIGNER_KEY) \
|
||||
--manifest kms.manifest \
|
||||
--output $@
|
||||
openssl rsa -in $(SGX_SIGNER_KEY) -pubout -out public_data/$(SGX_SIGNER_PUBLIC_KEY)
|
||||
|
||||
kms.sig: kms.manifest.sgx
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) *.manifest *.manifest.sgx *.sig OUTPUT scripts/testdir/*
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
|
@ -1,27 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SGX_SIGNER_KEY="/opt/cosmian-internal/cosmian-signer-key.pem"
|
||||
|
||||
mkdir -p /root/public_data/
|
||||
mkdir -p /root/private_data/
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
if ! [ -e "/dev/sgx_enclave" ]; then
|
||||
echo "You are not running on an sgx machine"
|
||||
echo "If you want to compute the MR_ENCLAVE, re-run with --emulation parameter"
|
||||
exit 1
|
||||
fi
|
||||
make SGX=1 SGX_SIGNER_KEY=$SGX_SIGNER_KEY KMS_USE_BOOTSTRAP_SERVER="${KMS_USE_BOOTSTRAP_SERVER}" KMS_USE_CERTBOT="${KMS_USE_CERTBOT}" KMS_CERTBOT_HOSTNAME="${KMS_CERTBOT_HOSTNAME}" KMS_CERTBOT_EMAIL="${KMS_CERTBOT_EMAIL}" KMS_CERTBOT_USE_TEE_KEY="${KMS_CERTBOT_USE_TEE_KEY}" && gramine-sgx ./kms
|
||||
elif [ $# -eq 1 ] && [ "$1" = "--emulation" ]; then
|
||||
mkdir /opt/cosmian-internal
|
||||
# Generate a dummy key. `MR_ENCLAVE` does not depend on it.
|
||||
openssl genrsa -3 -out $SGX_SIGNER_KEY 3072
|
||||
# Compile but don't start
|
||||
make SGX=1 SGX_SIGNER_KEY=$SGX_SIGNER_KEY KMS_USE_BOOTSTRAP_SERVER="${KMS_USE_BOOTSTRAP_SERVER}" KMS_USE_CERTBOT="${KMS_USE_CERTBOT}" KMS_CERTBOT_HOSTNAME="${KMS_CERTBOT_HOSTNAME}" KMS_CERTBOT_EMAIL="${KMS_CERTBOT_EMAIL}" KMS_CERTBOT_USE_TEE_KEY="${KMS_CERTBOT_USE_TEE_KEY}"
|
||||
# Note: if `public_data` is mounted inside the docker, the user can read `kms.manifest.kms` from outside the docker
|
||||
else
|
||||
echo "Usage: $0 [--emulation]"
|
||||
echo ""
|
||||
echo "Using --emulation enables you to get the MR_ENCLAVE of the enclave server"
|
||||
echo "You don't need to use an SGX machine to use --emulation param"
|
||||
fi
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"kms_server_url": "https://kms.sgx.ci.cosmian.dev:9998",
|
||||
"kms_access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjVVU1FrSVlULW9QMWZrcjQtNnRrciJ9.eyJuaWNrbmFtZSI6InRlY2giLCJuYW1lIjoidGVjaEBjb3NtaWFuLmNvbSIsInBpY3R1cmUiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci81MmZiMzFjOGNjYWQzNDU4MTIzZDRmYWQxNDA4NTRjZj9zPTQ4MCZyPXBnJmQ9aHR0cHMlM0ElMkYlMkZjZG4uYXV0aDAuY29tJTJGYXZhdGFycyUyRnRlLnBuZyIsInVwZGF0ZWRfYXQiOiIyMDIzLTA1LTMwVDA5OjMxOjExLjM4NloiLCJlbWFpbCI6InRlY2hAY29zbWlhbi5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOi8va21zLWNvc21pYW4uZXUuYXV0aDAuY29tLyIsImF1ZCI6IkszaXhldXhuVDVrM0Roa0tocWhiMXpYbjlFNjJGRXdJIiwiaWF0IjoxNjg1NDM5MDc0LCJleHAiOjE2ODU0NzUwNzQsInN1YiI6ImF1dGgwfDYzZDNkM2VhOTNmZjE2ANDJjNzdkZjkyOCIsInNpZCI6ImJnVUNuTTNBRjVxMlpaVHFxMTZwclBCMi11Z0NNaUNPIiwibm9uY2UiOiJVRUZWTlZWeVluWTVUbHBwWjJScGNqSmtVMEZ4TmxkUFEwc3dTVGMwWHpaV2RVVmtkVnBEVGxSMldnPT0ifQ.HmU9fFwZ-JjJVlSy_PTei3ys0upeWQbWWiESmKBtRSClGnAXJNCpwuP4Jw7fgKn-8IBf-PYmP1_54u2Rw3RcJFVl7EblVoGMghYxVq5hViGpd00st3VwZmyCwOUz2CE5RBnBAoES4C8xA3zWg6oau0xjFQbC3jNU20eyFYMDewXA8UXCHQrEiQ56ylqSbyqlBbQIWbmOO4m5w2WDkx0bVyyJ893JfIJr_NANEQMJITYo8Mp_iHCyKp7llsfgCt07xN8ZqnsrMsJ15zC1n50bHGrTQisxURS1dpuFXF1hfrxhzogxYMX8CEISjsFgROjPY84GRMmvpYZfyaJbDDql3A",
|
||||
"kms_database_secret": "eyJncm91cF9pZCI6MTY5NjE5MjAzMzQ1MDY0MDQxNjY1ODIyNzgwNjczNDY1ODkyNjcyLCJrZXkiOiJhN2EyNWY2YWUxMzExODMyYTBiYmRkZDNjMjk3ZjhjYTAxZTg4OWEzNzFlNjNhZmMyNjU4MDc2NzE1MmQ4YTA2In0=",
|
||||
"accept_invalid_certs": true
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
loader.entrypoint = "file:{{ gramine.libos }}"
|
||||
libos.entrypoint = "{{ entrypoint }}/server"
|
||||
|
||||
# We don't use argv, therefore we have to set argv[0]
|
||||
loader.argv0_override = "kms_server"
|
||||
# loader.argv_src_file = "file:scripts/args"
|
||||
|
||||
loader.log_level = "{{ log_level }}"
|
||||
|
||||
# Currently required for Tokio (eventfd is done by the host not the enclave, so less secure)
|
||||
sys.insecure__allow_eventfd = true
|
||||
# This specifies the stack size of each thread in each Gramine process
|
||||
# Note: if you remove that, the KMS won't work. Errors you can get:
|
||||
# - "thread panicked while processing panic. aborting."
|
||||
# - "The futex facility returned an unexpected error code."
|
||||
sys.stack.size = "1G"
|
||||
|
||||
sys.enable_extra_runtime_domain_names_conf = true
|
||||
|
||||
loader.env.LD_LIBRARY_PATH = "/lib:/lib64:{{ arch_libdir }}:/usr/{{ arch_libdir }}"
|
||||
loader.env.KMS_SGX_PUBLIC_SIGNER_KEY_FILENAME = "{{ sgx_signer_public_key }}"
|
||||
loader.env.KMS_TEE_DIR_PATH = "/public_data"
|
||||
loader.env.KMS_ROOT_DATA_PATH = "/private_data"
|
||||
loader.env.RUST_BACKTRACE="0"
|
||||
loader.env.KMS_USE_BOOTSTRAP_SERVER = "{{ kms_use_bootstrap_server }}"
|
||||
loader.env.KMS_USE_CERTBOT = "{{ kms_use_cerbot }}"
|
||||
loader.env.KMS_CERTBOT_HOSTNAME = "{{ kms_cerbot_hostname }}"
|
||||
loader.env.KMS_CERTBOT_EMAIL = "{{ kms_cerbot_email }}"
|
||||
loader.env.KMS_CERTBOT_USE_TEE_KEY = "{{ kms_cerbot_use_tee_key }}"
|
||||
|
||||
|
||||
|
||||
sgx.nonpie_binary = true
|
||||
sgx.remote_attestation = 'dcap'
|
||||
sgx.enclave_size = "16G"
|
||||
sgx.max_threads = 256
|
||||
sgx.debug = false
|
||||
|
||||
sgx.isvprodid = 1
|
||||
sgx.isvsvn = 10
|
||||
|
||||
# File to mount into the enclave
|
||||
fs.mounts = [
|
||||
{ type = "chroot", uri = "file:{{ gramine.runtimedir() }}", path = "/lib" },
|
||||
{ type = "chroot", uri = "file:{{ arch_libdir }}", path = "{{ arch_libdir }}" },
|
||||
{ type = "chroot", uri = "file:/usr/{{ arch_libdir }}", path = "/usr/{{ arch_libdir }}" },
|
||||
{ type = "chroot", uri = "file:/etc", path = "/etc" },
|
||||
{ type = "chroot", uri = "file:{{ entrypoint_abs }}", path = "{{ entrypoint }}" },
|
||||
{ type = "tmpfs", path = "/tmp" },
|
||||
{ type = "encrypted", uri = "file:private_data", path = "/private_data", key_name = "_sgx_mrenclave" },
|
||||
]
|
||||
|
||||
# Public path
|
||||
sgx.allowed_files = [
|
||||
"file:public_data"
|
||||
]
|
||||
|
||||
|
||||
# Files to hash at build time and allowed to be accessed in runtime if hashes match
|
||||
sgx.trusted_files = [
|
||||
"file:{{ entrypoint_abs }}/server",
|
||||
"file:{{ gramine.libos }}",
|
||||
"file:{{ gramine.runtimedir() }}/",
|
||||
"file:{{ arch_libdir }}/",
|
||||
"file:/etc/nsswitch.conf",
|
||||
"file:/etc/group",
|
||||
"file:/etc/passwd",
|
||||
"file:/etc/host.conf",
|
||||
"file:/etc/gai.conf",
|
||||
"file:/etc/resolv.conf",
|
||||
"file:/etc/localtime",
|
||||
"file:/etc/ld.so.cache",
|
||||
"file:{{ arch_libdir }}/libsodium.so.23",
|
||||
"file:/usr/lib/ssl/certs/",
|
||||
"file:/etc/ssl/certs/ca-certificates.crt",
|
||||
]
|
|
@ -12,6 +12,7 @@ path = "src/main.rs"
|
|||
[features]
|
||||
# Staging is used to run tests with the remote kms test server. Otherwise, the test runs a local kms server.
|
||||
staging = []
|
||||
fips = ["cosmian_kms_utils/fips"]
|
||||
|
||||
[dependencies]
|
||||
actix-web = { workspace = true }
|
||||
|
@ -23,20 +24,14 @@ cosmian_kms_client = { path = "../client" }
|
|||
cosmian_kms_utils = { path = "../utils" }
|
||||
cosmian_logger = { path = "../logger" }
|
||||
der = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
oauth2 = "4.4"
|
||||
## openssl is only used to parse PKCS#12 files because native support is not yet available in Rust yet.
|
||||
## It should not be used for anything else and will be removed once native support is available.
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
||||
pem = "3.0"
|
||||
rand = "0.8"
|
||||
ratls = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
tee_attestation = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
@ -54,6 +49,7 @@ cosmian_kms_client = { path = "../client", default-features = false }
|
|||
cosmian_kms_server = { path = "../server", features = [
|
||||
"insecure",
|
||||
], default-features = false }
|
||||
openssl = { workspace = true }
|
||||
predicates = "3.0"
|
||||
regex = { version = "1.10", default-features = false }
|
||||
tempfile = "3.8"
|
||||
|
|
|
@ -91,62 +91,6 @@ You can perform the following operations concerning to the users-to-objects perm
|
|||
- `remove` Remove an access authorization for an object to a user
|
||||
- `shared` List objects shared for the current user
|
||||
|
||||
### Quote and remote attestation
|
||||
|
||||
If the KMS server is running inside an enclave, you can and should verify its trustworthiness.
|
||||
|
||||
To do so, use `trust` subcommand. Doing that, the `cli` will:
|
||||
|
||||
- Ask the kms server to generate a quote containing the public certificate of the kms server and a nonce (a randomly generated string to make the quote unique each time)
|
||||
- Send the quote to Azure Microsoft to proceed a remote attestation
|
||||
- Proceed some trust checks
|
||||
- Export various files on your filesystem to let you manually verify them.
|
||||
|
||||
From [gramine docs](https://gramine.readthedocs.io/en/latest/sgx-intro.html#term-sgx-quote), you can read: "*The SGX quote is the proof of trustworthiness of the enclave and is used during Remote Attestation. The attesting enclave generates the enclave-specific SGX Report, sends the request to the Quoting Enclave using Local Attestation, and the Quoting Enclave returns back the SGX quote with the SGX report embedded in it. The resulting SGX quote contains the enclave's measurement, attributes and other security-relevant fields, and is tied to the identity of the Quoting Enclave to prove its authenticity. The obtained SGX quote may be later sent to the verifying remote party, which examines the SGX quote and gains trust in the remote enclave.*"
|
||||
|
||||
#### Quote report data
|
||||
|
||||
The report data contains attributes smartly chosen to make a decision on the trustworthiness of the enclave.
|
||||
|
||||
- The __ssl certificate__. This certificate is encrypted using the `mr_enclave` key. Therefore if the server is updated, the certificates will be also updated and the quote will vary. Moreover this parameter is public, so you are plenty aware when the certificate changes.
|
||||
- The __nonce__ to make the quote unique each time the user want a proof of trust. It uses an arbitrary and non predictable string. The kms server can't therefore send a previous verify version of the quote.
|
||||
|
||||
#### Automatic trust checks
|
||||
|
||||
The cli automatically checks:
|
||||
|
||||
- If the kms server runs inside an sgx enclave known by *Intel*
|
||||
- If the quote inside the remote attestation is the same than the quote returning by the enclave
|
||||
- If the `mr_enclave` and `mr_signer` are the same between the remote attestation and the quote
|
||||
- If the `mr_enclave` and `mr_signer` are the expected ones. See below.
|
||||
- If the current time is contained into the `iat` and the `exp` time of the remote attestation
|
||||
- If the quote's report data is both the same in the remote attestation and in the quote
|
||||
|
||||
#### `mr_signer`
|
||||
|
||||
This value enables you to verify that the KMS is running inside an enclave which belongs to *Cosmian*. Indeed this value is a `sha256` hash of the public key used to sign the enclave.
|
||||
|
||||
This value will be compute by the CLI and compared against the values obtained from the quote and the remote attestation.
|
||||
|
||||
If the value is altered, it could mean that you are not using the *Cosmian* KMS in the *Cosmian* infrastructures. You shouldn't proceed and you should report that incident to us.
|
||||
|
||||
#### `mr_enclave`
|
||||
|
||||
This value enables you to verify that the KMS code and libraries inside the enclave are the same as the code you can read on [*Cosmian* Github](https://github.com/Cosmian).
|
||||
|
||||
This value is not compute by the CLI. You can get the open-sourced KMS docker, read the `mr_enclave` value from it and give it to the CLI to check it. See [README.md](../../sgx/README.md#emulate) for more details.
|
||||
|
||||
If the value is altered, it could mean that you are not using the KMS from *Cosmian* but a modified one. You shouldn't proceed and you should report that incident to us.
|
||||
|
||||
#### Exported files
|
||||
|
||||
The files you can manually verify are:
|
||||
|
||||
- The quote: `quote.raw` and `quote.struct`
|
||||
- The manifest of the enclave containing the hashes of all trusted files and the running context (env variables, etc.): `manifest.sgx`
|
||||
- The remote attestation itself: `remote_attestation`
|
||||
- The enclave and the ssl certificate: `enclave.pub` and `ssl.cert`
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
|
@ -156,9 +100,7 @@ cargo test -p cosmian_kms_cli
|
|||
|
||||
A KMS server is started by the test. Make sure, you don't start another one by yourself.
|
||||
|
||||
You can also test using a remote KMS running inside an enclave. First, generate and start a docker as described in [README.md](../../sgx/README.md).
|
||||
|
||||
Then:
|
||||
You can also test using a remote KMS:
|
||||
|
||||
```sh
|
||||
cargo build --bin cosmian_kms_cli
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Args, Parser};
|
||||
use cosmian_kms_client::BootstrapRestClient;
|
||||
|
||||
use crate::{cli_bail, error::CliError};
|
||||
|
||||
/// Provide configuration and start the KMS server via the bootstrap server.
|
||||
///
|
||||
/// When the server is started using the bootstrap server,
|
||||
/// this command is used to provide configuration information, such as
|
||||
/// - database configuration
|
||||
/// - PKCS12 to use as the KMS HTTPS server certificate
|
||||
/// and start the configured KMS server.
|
||||
#[derive(Parser)]
|
||||
#[clap(verbatim_doc_comment)]
|
||||
pub struct BootstrapServerAction {
|
||||
#[clap(flatten)]
|
||||
pub db: DatabaseConfig,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub pkcs12: Pkcs12Config,
|
||||
}
|
||||
|
||||
impl BootstrapServerAction {
|
||||
pub async fn process(
|
||||
&self,
|
||||
bootstrap_rest_client: &BootstrapRestClient,
|
||||
) -> Result<(), CliError> {
|
||||
println!("Server response:");
|
||||
|
||||
// set the password if provided, if not set the empty string
|
||||
bootstrap_rest_client
|
||||
.set_pkcs12_password(&self.pkcs12.https_p12_password)
|
||||
.await?;
|
||||
|
||||
// upload the PKCS12 file if provided
|
||||
if let Some(pkcs12_file) = &self.pkcs12.https_p12_file {
|
||||
let response = bootstrap_rest_client.upload_pkcs12(pkcs12_file).await?;
|
||||
println!(" -> {}", response.success);
|
||||
}
|
||||
|
||||
// set the database configuration
|
||||
if let Some(database_type) = &self.db.database_type {
|
||||
let response = match database_type.as_str() {
|
||||
"redis-findex" => {
|
||||
let database_url = self.db.database_url.as_ref().ok_or_else(|| {
|
||||
CliError::Default("Missing the database url for redis-findex".to_string())
|
||||
})?;
|
||||
let redis_master_password =
|
||||
self.db.redis_master_password.as_ref().ok_or_else(|| {
|
||||
CliError::Default(
|
||||
"Missing the Redis master password for redis-findex".to_string(),
|
||||
)
|
||||
})?;
|
||||
let redis_findex_label =
|
||||
self.db.redis_findex_label.as_ref().ok_or_else(|| {
|
||||
CliError::Default(
|
||||
"Missing the Findex label for redis-findex".to_string(),
|
||||
)
|
||||
})?;
|
||||
bootstrap_rest_client
|
||||
.set_redis_findex_config(
|
||||
database_url,
|
||||
redis_master_password,
|
||||
redis_findex_label,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
"postgresql" => {
|
||||
if let Some(database_url) = &self.db.database_url {
|
||||
bootstrap_rest_client
|
||||
.set_postgresql_config(database_url)
|
||||
.await?
|
||||
} else {
|
||||
cli_bail!("Missing the database url for postgresql")
|
||||
}
|
||||
}
|
||||
"mysql" => {
|
||||
if let Some(database_url) = &self.db.database_url {
|
||||
bootstrap_rest_client.set_mysql_config(database_url).await?
|
||||
} else {
|
||||
cli_bail!("Missing the database url for mysql")
|
||||
}
|
||||
}
|
||||
"sqlite" => {
|
||||
bootstrap_rest_client
|
||||
.set_sqlite_config(&self.db.sqlite_path)
|
||||
.await?
|
||||
}
|
||||
"sqlite-enc" => {
|
||||
bootstrap_rest_client
|
||||
.set_sqlite_enc_config(&self.db.sqlite_path)
|
||||
.await?
|
||||
}
|
||||
_ => {
|
||||
cli_bail!("Invalid database type");
|
||||
}
|
||||
};
|
||||
println!(" -> {}", response.success);
|
||||
}
|
||||
|
||||
let response = bootstrap_rest_client
|
||||
.start_kms_server(self.db.clear_database)
|
||||
.await?;
|
||||
println!(" -> {}", response.success);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for the database
|
||||
#[derive(Args, Clone)]
|
||||
pub struct DatabaseConfig {
|
||||
/// The database type of the KMS server:
|
||||
/// - postgresql: PostgreSQL. The database url must be provided
|
||||
/// - mysql: MySql or MariaDB. The database url must be provided
|
||||
/// - sqlite: SQLite. The data will be stored at the sqlite_path directory
|
||||
/// - sqlite-enc: SQLite encrypted at rest. The data will be stored at the sqlite_path directory.
|
||||
/// A key must be supplied on every call
|
||||
/// - redis-findex: and redis database with encrypted data and encrypted indexes thanks to Findex.
|
||||
/// The Redis database url must be provided, as well as the redis-master-password and the redis-findex-label
|
||||
/// _
|
||||
#[clap(
|
||||
long,
|
||||
value_parser(["postgresql", "mysql", "sqlite", "sqlite-enc", "redis-findex"]),
|
||||
verbatim_doc_comment
|
||||
)]
|
||||
pub database_type: Option<String>,
|
||||
|
||||
/// The url of the database for postgresql, mysql or findex-redis
|
||||
#[clap(
|
||||
long,
|
||||
required_if_eq_any([("database_type", "postgresql"), ("database_type", "mysql"), ("database_type", "redis-findex")])
|
||||
)]
|
||||
pub database_url: Option<String>,
|
||||
|
||||
/// The directory path of the sqlite or sqlite-enc
|
||||
#[clap(
|
||||
long,
|
||||
default_value = "./sqlite-data",
|
||||
required_if_eq_any([("database_type", "sqlite"), ("database_type", "sqlite-enc")])
|
||||
)]
|
||||
pub sqlite_path: PathBuf,
|
||||
|
||||
/// redis-findex: a master password used to encrypt the Redis data and indexes
|
||||
#[clap(long, required_if_eq("database_type", "redis-findex"))]
|
||||
pub redis_master_password: Option<String>,
|
||||
|
||||
/// redis-findex: a public arbitrary label that can be changed to rotate the Findex ciphertexts
|
||||
/// without changing the key
|
||||
#[clap(long, required_if_eq("database_type", "redis-findex"))]
|
||||
pub redis_findex_label: Option<String>,
|
||||
|
||||
/// Clear the database on start.
|
||||
/// WARNING: This will delete ALL the data in the database
|
||||
#[clap(long, default_value = "false", verbatim_doc_comment)]
|
||||
pub clear_database: bool,
|
||||
}
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub struct Pkcs12Config {
|
||||
/// The KMS server optional PKCS#12 Certificates and Key file. If provided, this will start the server in HTTPS mode.
|
||||
#[clap(long)]
|
||||
pub https_p12_file: Option<PathBuf>,
|
||||
|
||||
/// The password to open the PKCS#12 Certificates and Key file if not an empty string
|
||||
#[clap(long, default_value = "")]
|
||||
pub https_p12_password: String,
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
pub mod access;
|
||||
pub mod bootstrap;
|
||||
pub mod certificates;
|
||||
pub mod cover_crypt;
|
||||
pub mod elliptic_curves;
|
||||
|
@ -9,5 +8,4 @@ pub mod markdown;
|
|||
pub mod new_database;
|
||||
pub mod shared;
|
||||
pub mod symmetric;
|
||||
pub mod verify;
|
||||
pub mod version;
|
||||
|
|
|
@ -2,14 +2,12 @@ use std::path::PathBuf;
|
|||
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use clap::Parser;
|
||||
use cloudproof::reexport::crypto_core::CsRng;
|
||||
use cosmian_kmip::kmip::kmip_types::CryptographicAlgorithm;
|
||||
use cosmian_kms_client::KmsRestClient;
|
||||
use cosmian_kms_utils::crypto::{
|
||||
password_derivation::derive_key_from_password, symmetric::create_symmetric_key,
|
||||
wrap::wrap_key_block,
|
||||
};
|
||||
use rand::SeedableRng;
|
||||
|
||||
use crate::{
|
||||
actions::shared::{
|
||||
|
@ -93,8 +91,7 @@ impl WrapKeyAction {
|
|||
cli_bail!("one of the wrapping options must be specified");
|
||||
};
|
||||
|
||||
let mut rng = CsRng::from_entropy();
|
||||
wrap_key_block(&mut rng, object.key_block_mut()?, &wrapping_key, None)?;
|
||||
wrap_key_block(object.key_block_mut()?, &wrapping_key, None)?;
|
||||
|
||||
// set the output file path to the input file path if not specified
|
||||
let output_file = self
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use cosmian_kms_utils::tee::forge_report_data;
|
||||
use openssl::x509::X509;
|
||||
use rand::Rng;
|
||||
use ratls::verify::get_server_certificate;
|
||||
use tee_attestation::{verify_quote, TeeMeasurement};
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
use crate::{
|
||||
config::{CliConf, TeeConf},
|
||||
error::{result::CliResultHelper, CliError},
|
||||
};
|
||||
|
||||
/// Query the KMS to check its trustworthiness. Validate the TLS certificate to use in any further queries.
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct TeeAction {
|
||||
/// The path to store working files (quote, certificate, ...)
|
||||
#[clap(default_value = "/tmp/kms")]
|
||||
export_path: PathBuf,
|
||||
}
|
||||
|
||||
impl TeeAction {
|
||||
pub async fn process(&self, conf: &CliConf) -> Result<(), CliError> {
|
||||
// Create the export directory if it does not exist
|
||||
if !Path::new(&self.export_path).exists() {
|
||||
fs::create_dir_all(&self.export_path)?;
|
||||
}
|
||||
|
||||
let server_url = conf.kms_server_url()?;
|
||||
|
||||
// Get the KMS certificate
|
||||
let certificate = get_server_certificate(
|
||||
server_url
|
||||
.host_str()
|
||||
.ok_or_else(|| CliError::Default("Host not found in server url".to_string()))?,
|
||||
server_url.port().unwrap_or(443).into(),
|
||||
)
|
||||
.map_err(|e| CliError::Default(format!("Can't get KMS server certificate: {e}")))?;
|
||||
|
||||
let certificate = X509::from_der(&certificate)
|
||||
.map_err(|e| CliError::Default(format!("Can't convert certificate from DER: {e}")))?
|
||||
.to_pem()
|
||||
.map_err(|e| CliError::Default(format!("Can't convert certificate to PEM: {e}")))?;
|
||||
|
||||
let cert_path = self.export_path.join("cert.pem");
|
||||
fs::write(&cert_path, &certificate)?;
|
||||
println!("The KMS PEM certificate has been saved at {cert_path:?}");
|
||||
|
||||
// Let's use this certificate when querying the KMS to get the quote
|
||||
let mut local_conf = conf.clone();
|
||||
let verified_cert = Some(String::from_utf8_lossy(&certificate).to_string());
|
||||
if let Some(mut local_tee_conf) = local_conf.tee_conf {
|
||||
local_tee_conf.verified_cert = verified_cert;
|
||||
local_conf.tee_conf = Some(local_tee_conf);
|
||||
} else {
|
||||
local_conf.tee_conf = Some(TeeConf {
|
||||
verified_cert,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
let kms_rest_client = local_conf.initialize_kms_client()?;
|
||||
|
||||
// Generate a nonce to make the quote unique. Use an arbitrary and non predictable string.
|
||||
let nonce = rand::thread_rng().gen::<[u8; 32]>();
|
||||
|
||||
let nonce_path = self.export_path.join("nonce.bin");
|
||||
fs::write(&nonce_path, nonce)?;
|
||||
println!("The random nonce has been saved at {nonce_path:?}");
|
||||
|
||||
// Get the quote from the kms
|
||||
let quote = kms_rest_client
|
||||
.get_attestation_report(&nonce)
|
||||
.await
|
||||
.with_context(|| "Can't execute the query on the kms server")?;
|
||||
|
||||
// Save the quote
|
||||
let quote_raw_path = self.export_path.join("quote.bin");
|
||||
fs::write("e_raw_path, "e)?;
|
||||
println!("The raw quote has been saved at {quote_raw_path:?}");
|
||||
|
||||
// Let's verify the quote
|
||||
let report_data = forge_report_data(&nonce, &certificate)?;
|
||||
|
||||
let tee_conf = if let Some(tee_conf) = conf.tee_conf.clone() {
|
||||
tee_conf.try_into()?
|
||||
} else {
|
||||
TeeMeasurement::default()
|
||||
};
|
||||
|
||||
match spawn_blocking(move || verify_quote("e, &report_data, tee_conf))
|
||||
.await
|
||||
.map_err(|e| CliError::Default(format!("Can't verify quote: {e}")))?
|
||||
{
|
||||
Ok(()) => println!("Verification succeed"),
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
|
||||
// Now, the user doesn't need to verify the quote each time it queries the KMS since it forces the certificate to be that one.
|
||||
local_conf.save()?;
|
||||
|
||||
println!("You configuration file has been updated to secure the further calls to the KMS");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -5,12 +5,10 @@ use std::{
|
|||
path::PathBuf,
|
||||
};
|
||||
|
||||
use cosmian_kms_client::{BootstrapRestClient, KmsRestClient};
|
||||
use hex::decode;
|
||||
use openssl::x509::X509;
|
||||
use cosmian_kms_client::KmsRestClient;
|
||||
use der::{DecodePem, Encode};
|
||||
use rustls::Certificate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tee_attestation::{SevMeasurement, SgxMeasurement, TeeMeasurement};
|
||||
use url::Url;
|
||||
|
||||
use crate::error::{result::CliResultHelper, CliError};
|
||||
|
@ -58,83 +56,6 @@ fn not(b: &bool) -> bool {
|
|||
!*b
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone, Default)]
|
||||
pub struct TeeConf {
|
||||
// verified_cert = Some(PEM) means that the leaf certificate needs to be the exact one
|
||||
// used when verifying the quote. This option should be set if the KMS has been deployed on a TEE. None is unsecured.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) verified_cert: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) mr_enclave: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) public_signer_key: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) sev_measurement: Option<String>,
|
||||
}
|
||||
|
||||
impl TryInto<TeeMeasurement> for TeeConf {
|
||||
type Error = CliError;
|
||||
|
||||
fn try_into(self) -> Result<TeeMeasurement, Self::Error> {
|
||||
let mrenclave = if let Some(v) = &self.mr_enclave {
|
||||
Some(
|
||||
decode(v)
|
||||
.map_err(|_| {
|
||||
CliError::Default("Invalid hexadecimal format for mr enclave".to_string())
|
||||
})?
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.map_err(|e| {
|
||||
CliError::Default(format!("Bad MR enclave bytes-size: error: {e}"))
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let sev_measurement = if let Some(v) = &self.sev_measurement {
|
||||
Some(
|
||||
decode(v)
|
||||
.map_err(|_| {
|
||||
CliError::Default("Invalid hexadecimal format for mr enclave".to_string())
|
||||
})?
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.map_err(|e| {
|
||||
CliError::Default(format!("Bad SEV measurement bytes-size: error: {e}"))
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let measurement = match (self.public_signer_key, mrenclave, sev_measurement) {
|
||||
(None, None, None) => TeeMeasurement {
|
||||
sgx: None,
|
||||
sev: None,
|
||||
},
|
||||
(Some(s), Some(e), None) => TeeMeasurement {
|
||||
sgx: Some(SgxMeasurement {
|
||||
public_signer_key_pem: s.to_string(),
|
||||
mr_enclave: e,
|
||||
}),
|
||||
sev: None,
|
||||
},
|
||||
(None, None, Some(m)) => TeeMeasurement {
|
||||
sgx: None,
|
||||
sev: Some(SevMeasurement(m)),
|
||||
},
|
||||
_ => {
|
||||
return Err(CliError::Default(
|
||||
"Bad measurements combination".to_string(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(measurement)
|
||||
}
|
||||
}
|
||||
|
||||
/// The configuration that is used by the Login command
|
||||
/// to perform the `OAuth2` authorize code flow and obtain an access token.
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
|
||||
|
@ -165,9 +86,7 @@ pub struct CliConf {
|
|||
pub(crate) accept_invalid_certs: bool,
|
||||
pub(crate) kms_server_url: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) bootstrap_server_url: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tee_conf: Option<TeeConf>,
|
||||
pub(crate) verified_cert: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) kms_access_token: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
@ -186,14 +105,6 @@ impl CliConf {
|
|||
pub fn kms_server_url(&self) -> Result<Url, CliError> {
|
||||
Ok(Url::parse(&self.kms_server_url)?)
|
||||
}
|
||||
|
||||
pub fn bootstrap_server_url(&self) -> Result<Option<Url>, CliError> {
|
||||
if let Some(url) = &self.bootstrap_server_url {
|
||||
Ok(Some(Url::parse(url)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CliConf {
|
||||
|
@ -201,8 +112,7 @@ impl Default for CliConf {
|
|||
Self {
|
||||
accept_invalid_certs: false,
|
||||
kms_server_url: "http://0.0.0.0:9998".to_string(),
|
||||
bootstrap_server_url: None,
|
||||
tee_conf: None,
|
||||
verified_cert: None,
|
||||
kms_access_token: None,
|
||||
kms_database_secret: None,
|
||||
ssl_client_pkcs12_path: None,
|
||||
|
@ -221,7 +131,6 @@ impl Default for CliConf {
|
|||
/// {
|
||||
/// "accept_invalid_certs": false,
|
||||
/// "kms_server_url": "http://127.0.0.1:9998",
|
||||
/// "bootstrap_server_url": "https://127.0.0.1:9998",
|
||||
/// "kms_access_token": "AA...AAA",
|
||||
/// "kms_database_secret": "BB...BBB",
|
||||
/// "ssl_client_pkcs12_path": "/path/to/client.p12",
|
||||
|
@ -301,17 +210,12 @@ impl CliConf {
|
|||
self.ssl_client_pkcs12_password.as_deref(),
|
||||
self.kms_database_secret.as_deref(),
|
||||
self.accept_invalid_certs,
|
||||
match &self.tee_conf {
|
||||
Some(tee_conf) => {
|
||||
if let Some(certificate) = &tee_conf.verified_cert {
|
||||
if let Some(certificate) = &self.verified_cert {
|
||||
Some(Certificate(
|
||||
X509::from_pem(certificate.as_bytes())?.to_der()?,
|
||||
x509_cert::Certificate::from_pem(certificate.as_bytes())?.to_der()?,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
self.jwe_public_key.as_deref(),
|
||||
)
|
||||
|
@ -324,31 +228,6 @@ impl CliConf {
|
|||
|
||||
Ok(kms_rest_client)
|
||||
}
|
||||
|
||||
pub fn initialize_bootstrap_client(&self) -> Result<BootstrapRestClient, CliError> {
|
||||
// Instantiate a Bootstrap server REST client with the given configuration
|
||||
let bootstrap_rest_client = BootstrapRestClient::instantiate(
|
||||
self.bootstrap_server_url
|
||||
.as_ref()
|
||||
.unwrap_or(&self.kms_server_url.replace("http://", "https://")),
|
||||
self.kms_access_token.as_deref(),
|
||||
self.ssl_client_pkcs12_path.as_deref(),
|
||||
self.ssl_client_pkcs12_password.as_deref(),
|
||||
if let Some(tee_conf) = self.tee_conf.clone() {
|
||||
tee_conf.try_into()?
|
||||
} else {
|
||||
TeeMeasurement::default()
|
||||
},
|
||||
)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Unable to instantiate a Bootstrap server REST client {}",
|
||||
&self.kms_server_url
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(bootstrap_rest_client)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -8,7 +8,6 @@ use cosmian_kmip::{
|
|||
};
|
||||
use cosmian_kms_client::RestClientError;
|
||||
use cosmian_kms_utils::error::KmipUtilsError;
|
||||
use openssl::error::ErrorStack;
|
||||
use pem::PemError;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -45,10 +44,6 @@ pub enum CliError {
|
|||
#[error("Server error: {0}")]
|
||||
ServerError(String),
|
||||
|
||||
// Any errors related to a bad behavior of the server concerning the SGX environment
|
||||
#[error("Unexpected sgx error: {0}")]
|
||||
SGXError(String),
|
||||
|
||||
// Any actions of the user which is not allowed
|
||||
#[error("Access denied: {0}")]
|
||||
Unauthorized(String),
|
||||
|
@ -73,10 +68,6 @@ pub enum CliError {
|
|||
#[error("{0}")]
|
||||
Default(String),
|
||||
|
||||
// TEE errors
|
||||
#[error(transparent)]
|
||||
TeeAttestationError(#[from] tee_attestation::error::Error),
|
||||
|
||||
// Url parsing errors
|
||||
#[error(transparent)]
|
||||
UrlParsing(#[from] url::ParseError),
|
||||
|
@ -118,12 +109,6 @@ impl From<cloudproof::reexport::crypto_core::reexport::pkcs8::Error> for CliErro
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ErrorStack> for CliError {
|
||||
fn from(e: ErrorStack) -> Self {
|
||||
Self::Conversion(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TryFromSliceError> for CliError {
|
||||
fn from(e: TryFromSliceError) -> Self {
|
||||
Self::Conversion(e.to_string())
|
||||
|
|
|
@ -4,7 +4,6 @@ use clap::{CommandFactory, Parser, Subcommand};
|
|||
use cosmian_kms_cli::{
|
||||
actions::{
|
||||
access::AccessAction,
|
||||
bootstrap::BootstrapServerAction,
|
||||
certificates::CertificatesCommands,
|
||||
cover_crypt::CovercryptCommands,
|
||||
elliptic_curves::EllipticCurveCommands,
|
||||
|
@ -14,14 +13,12 @@ use cosmian_kms_cli::{
|
|||
new_database::NewDatabaseAction,
|
||||
shared::{GetAttributesAction, LocateObjectsAction},
|
||||
symmetric::SymmetricCommands,
|
||||
verify::TeeAction,
|
||||
version::ServerVersionAction,
|
||||
},
|
||||
config::CliConf,
|
||||
error::CliError,
|
||||
};
|
||||
use cosmian_logger::log_utils::log_init;
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
@ -34,7 +31,6 @@ struct Cli {
|
|||
enum CliCommands {
|
||||
#[command(subcommand)]
|
||||
AccessRights(AccessAction),
|
||||
BootstrapStart(BootstrapServerAction),
|
||||
#[command(subcommand)]
|
||||
Cc(CovercryptCommands),
|
||||
#[command(subcommand)]
|
||||
|
@ -47,7 +43,6 @@ enum CliCommands {
|
|||
ServerVersion(ServerVersionAction),
|
||||
#[command(subcommand)]
|
||||
Sym(SymmetricCommands),
|
||||
Verify(TeeAction),
|
||||
Login(LoginAction),
|
||||
Logout(LogoutAction),
|
||||
#[clap(hide = true)]
|
||||
|
@ -68,19 +63,6 @@ async fn main_() -> Result<(), CliError> {
|
|||
let opts = Cli::parse();
|
||||
let conf = CliConf::load()?;
|
||||
|
||||
if let CliCommands::Verify(action) = opts.command {
|
||||
action.process(&conf).await?;
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if let CliCommands::BootstrapStart(action) = opts.command {
|
||||
let bootstrap_rest_client = spawn_blocking(move || conf.initialize_bootstrap_client())
|
||||
.await
|
||||
.map_err(|e| CliError::Default(e.to_string()))??;
|
||||
action.process(&bootstrap_rest_client).await?;
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if let CliCommands::Markdown(action) = opts.command {
|
||||
let command = <Cli as CommandFactory>::command();
|
||||
action.process(&command).await?;
|
||||
|
@ -98,7 +80,6 @@ async fn main_() -> Result<(), CliError> {
|
|||
CliCommands::Certificates(action) => action.process(&kms_rest_client).await?,
|
||||
CliCommands::NewDatabase(action) => action.process(&kms_rest_client).await?,
|
||||
CliCommands::ServerVersion(action) => action.process(&kms_rest_client).await?,
|
||||
CliCommands::BootstrapStart(_) | CliCommands::Verify(_) => {}
|
||||
CliCommands::GetAttributes(action) => action.process(&kms_rest_client).await?,
|
||||
CliCommands::Login(action) => action.process().await?,
|
||||
CliCommands::Logout(action) => action.process().await?,
|
||||
|
|
|
@ -23,22 +23,22 @@ pub async fn test_all_authentications() -> Result<(), CliError> {
|
|||
// let us not make other test cases fail
|
||||
const PORT: u16 = 9999;
|
||||
// plaintext no auth
|
||||
let ctx = start_test_server_with_options(PORT, false, false, false, false, false).await;
|
||||
let ctx = start_test_server_with_options(PORT, false, false, false, false).await;
|
||||
run_cli_command(&ctx.owner_cli_conf_path);
|
||||
ctx.stop_server().await;
|
||||
|
||||
// plaintext token auth
|
||||
let ctx = start_test_server_with_options(PORT, true, false, false, false, false).await;
|
||||
let ctx = start_test_server_with_options(PORT, true, false, false, false).await;
|
||||
run_cli_command(&ctx.owner_cli_conf_path);
|
||||
ctx.stop_server().await;
|
||||
|
||||
// tls token auth
|
||||
let ctx = start_test_server_with_options(PORT, true, true, false, false, false).await;
|
||||
let ctx = start_test_server_with_options(PORT, true, true, false, false).await;
|
||||
run_cli_command(&ctx.owner_cli_conf_path);
|
||||
ctx.stop_server().await;
|
||||
|
||||
// tls client cert auth
|
||||
let ctx = start_test_server_with_options(PORT, false, true, true, false, false).await;
|
||||
let ctx = start_test_server_with_options(PORT, false, true, true, false).await;
|
||||
run_cli_command(&ctx.owner_cli_conf_path);
|
||||
ctx.stop_server().await;
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
use std::process::Command;
|
||||
|
||||
use assert_cmd::prelude::*;
|
||||
|
||||
use super::{utils::recover_cmd_logs, PROG_NAME};
|
||||
use crate::{
|
||||
config::KMS_CLI_CONF_ENV, error::CliError, tests::utils::start_test_server_with_options,
|
||||
};
|
||||
|
||||
pub(crate) const SUB_COMMAND: &str = "bootstrap-start";
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Need a tee runner to test this feature
|
||||
pub async fn test_bootstrap_server() -> Result<(), CliError> {
|
||||
// init the test server
|
||||
// since we are going to rewrite the conf, use a different port
|
||||
let ctx = start_test_server_with_options(29997, false, false, false, false, true).await;
|
||||
|
||||
let mut args: Vec<&str> = vec![];
|
||||
// No database parameters are supplied, start should fail
|
||||
assert!(run_bootstrap_start(&ctx.owner_cli_conf_path, &args).is_err());
|
||||
|
||||
// The database type is not supplied, start should fail
|
||||
args.extend_from_slice(&["--sqlite-path", "./sqlite-data"]);
|
||||
assert!(run_bootstrap_start(&ctx.owner_cli_conf_path, &args).is_err());
|
||||
|
||||
// The database type is supplied, start should succeed (in HTTP mode)
|
||||
args.extend_from_slice(&["--database-type", "sqlite"]);
|
||||
assert!(run_bootstrap_start(&ctx.owner_cli_conf_path, &args).is_ok());
|
||||
|
||||
// The PKCS12 password is not supplied: start should fail
|
||||
let mut args: Vec<&str> = vec![
|
||||
"--https-p12-file",
|
||||
"test_data/certificates/kmserver.acme.com.p12",
|
||||
];
|
||||
assert!(run_bootstrap_start(&ctx.owner_cli_conf_path, &args).is_err());
|
||||
|
||||
// The PKCS12 password is supplied start should succeed (in HTTPS mode)
|
||||
args.extend_from_slice(&["--https-p12-password", "password"]);
|
||||
assert!(run_bootstrap_start(&ctx.owner_cli_conf_path, &args).is_ok());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_bootstrap_start(cli_conf_path: &str, args: &[&str]) -> Result<String, CliError> {
|
||||
let mut cmd = Command::cargo_bin(PROG_NAME)?;
|
||||
cmd.env(KMS_CLI_CONF_ENV, cli_conf_path);
|
||||
cmd.env("RUST_LOG", "cosmian_kms_cli=info");
|
||||
cmd.arg(SUB_COMMAND).args(args);
|
||||
|
||||
let output = recover_cmd_logs(&mut cmd);
|
||||
if output.status.success() {
|
||||
let output = std::str::from_utf8(&output.stdout)?;
|
||||
return Ok(output.to_string())
|
||||
}
|
||||
|
||||
Err(CliError::Default(
|
||||
std::str::from_utf8(&output.stderr)?.to_owned(),
|
||||
))
|
||||
}
|
|
@ -395,26 +395,67 @@ async fn import_encrypt_decrypt(curve_name: &str) -> Result<(), CliError> {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(feature = "fips"))]
|
||||
// P-192 should not be used in FIPS mode. See NIST.SP.800-186 - Section 3.2.1.1.
|
||||
async fn test_certificate_encrypt_using_prime192() -> Result<(), CliError> {
|
||||
import_encrypt_decrypt("prime192v1").await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "fips")]
|
||||
async fn test_certificate_encrypt_using_prime224() -> Result<(), CliError> {
|
||||
let err_check = import_encrypt_decrypt("secp224r1").await;
|
||||
|
||||
// Only RSA KEM allowed in FIPS mode. Fix with issue #112.
|
||||
assert!(err_check.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(feature = "fips"))]
|
||||
async fn test_certificate_encrypt_using_prime224() -> Result<(), CliError> {
|
||||
import_encrypt_decrypt("secp224r1").await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(feature = "fips"))]
|
||||
// Edwards curve shall be used **for digital signature only**.
|
||||
// See NIST.SP.800-186 - Section 3.1.2 table 2 and NIST.FIPS.186-5.
|
||||
async fn test_certificate_encrypt_using_ed25519() -> Result<(), CliError> {
|
||||
import_encrypt_decrypt("ED25519").await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "fips")]
|
||||
async fn test_certificate_encrypt_using_prime256() -> Result<(), CliError> {
|
||||
let err_check = import_encrypt_decrypt("prime256v1").await;
|
||||
|
||||
// Only RSA KEM allowed in FIPS mode. Fix with issue #112.
|
||||
assert!(err_check.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(feature = "fips"))]
|
||||
async fn test_certificate_encrypt_using_prime256() -> Result<(), CliError> {
|
||||
import_encrypt_decrypt("prime256v1").await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "fips")]
|
||||
async fn test_certificate_encrypt_using_secp384r1() -> Result<(), CliError> {
|
||||
let err_check = import_encrypt_decrypt("secp384r1").await;
|
||||
|
||||
// Only RSA KEM allowed in FIPS mode. Fix with issue #112.
|
||||
assert!(err_check.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(not(feature = "fips"))]
|
||||
async fn test_certificate_encrypt_using_secp384r1() -> Result<(), CliError> {
|
||||
import_encrypt_decrypt("secp384r1").await
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
mod access;
|
||||
mod auth_tests;
|
||||
mod bootstrap_server;
|
||||
mod certificates;
|
||||
mod cover_crypt;
|
||||
mod elliptic_curve;
|
||||
mod new_database;
|
||||
mod sgx;
|
||||
mod shared;
|
||||
mod symmetric;
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ async fn test_multiple_databases() -> Result<(), CliError> {
|
|||
let tmp_path = tmp_dir.path();
|
||||
// init the test server
|
||||
// since we are going to rewrite the conf, use a different port
|
||||
let ctx = start_test_server_with_options(9997, true, false, false, false, false).await;
|
||||
let ctx = start_test_server_with_options(9997, true, false, false, false).await;
|
||||
|
||||
// create a symmetric key in the default encrypted database
|
||||
let key_1 = create_symmetric_key(&ctx.owner_cli_conf_path, None, None, None, &[])?;
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
use std::process::Command;
|
||||
|
||||
use assert_cmd::prelude::*;
|
||||
use predicates::prelude::*;
|
||||
|
||||
use crate::{
|
||||
config::KMS_CLI_CONF_ENV,
|
||||
error::CliError,
|
||||
tests::{
|
||||
utils::{init_test_server, ONCE},
|
||||
CONF_PATH, PROG_NAME,
|
||||
},
|
||||
};
|
||||
|
||||
const SUB_COMMAND: &str = "trust";
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_quote() -> Result<(), CliError> {
|
||||
ONCE.get_or_init(init_test_server).await;
|
||||
|
||||
let mut cmd = Command::cargo_bin(PROG_NAME)?;
|
||||
cmd.env(KMS_CLI_CONF_ENV, CONF_PATH);
|
||||
cmd.env("RUST_LOG", "cosmian_kms_cli=info");
|
||||
cmd.arg(SUB_COMMAND)
|
||||
.args(vec!["--mr-enclave", "dummy", "/tmp"]);
|
||||
recover_cmd_logs(&mut cmd);
|
||||
cmd.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains(
|
||||
"You can check all these files manually.",
|
||||
))
|
||||
.stdout(predicate::str::contains(
|
||||
"... Remote attestation checking Ok",
|
||||
))
|
||||
.stdout(predicate::str::contains("... MR signer checking Ok"))
|
||||
.stdout(predicate::str::contains("... Quote checking Ok"))
|
||||
.stdout(predicate::str::contains("... Date checking Ok "))
|
||||
.stdout(predicate::str::contains(
|
||||
"... Quote report data (manifest, kms certificates and nonce) checking Ok ",
|
||||
));
|
||||
|
||||
// We do not test: "... MR enclave checking Ok" because we don't know yet how to pass `--mr-enclave` in the CI
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
//mod integration_tests;
|
|
@ -1,9 +1,12 @@
|
|||
use std::{path::Path, process::Command};
|
||||
|
||||
use assert_cmd::prelude::*;
|
||||
use cosmian_kmip::kmip::{
|
||||
use cosmian_kmip::{
|
||||
kmip::{
|
||||
kmip_data_structures::KeyMaterial,
|
||||
kmip_types::{CryptographicAlgorithm, KeyFormatType, RecommendedCurve},
|
||||
},
|
||||
openssl::pad_be_bytes,
|
||||
};
|
||||
use openssl::pkey::{Id, PKey};
|
||||
use tempfile::TempDir;
|
||||
|
@ -344,7 +347,11 @@ pub async fn test_export_x25519() -> Result<(), CliError> {
|
|||
_ => panic!("Invalid key value type"),
|
||||
};
|
||||
assert_eq!(recommended_curve, &RecommendedCurve::CURVE25519);
|
||||
let pkey_1 = PKey::private_key_from_raw_bytes(&d.to_bytes_be(), Id::X25519)?;
|
||||
let mut d_vec = d.to_bytes_be();
|
||||
// 32 is privkey size on x25519.
|
||||
pad_be_bytes(&mut d_vec, 32);
|
||||
println!("dvec size is {:?}", d_vec.len());
|
||||
let pkey_1 = PKey::private_key_from_raw_bytes(&d_vec, Id::X25519).unwrap();
|
||||
|
||||
// Export the bytes only
|
||||
export_key(
|
||||
|
@ -358,11 +365,11 @@ pub async fn test_export_x25519() -> Result<(), CliError> {
|
|||
false,
|
||||
)?;
|
||||
let bytes = read_bytes_from_file(&tmp_path.join("output.export.bytes"))?;
|
||||
let pkey_2 = PKey::private_key_from_der(&bytes)?;
|
||||
let pkey_2 = PKey::private_key_from_der(&bytes).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
pkey_1.private_key_to_pkcs8()?,
|
||||
pkey_2.private_key_to_pkcs8()?
|
||||
pkey_1.private_key_to_pkcs8().unwrap(),
|
||||
pkey_2.private_key_to_pkcs8().unwrap()
|
||||
);
|
||||
|
||||
//
|
||||
|
@ -399,7 +406,7 @@ pub async fn test_export_x25519() -> Result<(), CliError> {
|
|||
_ => panic!("Invalid key value type"),
|
||||
};
|
||||
assert_eq!(recommended_curve, &RecommendedCurve::CURVE25519);
|
||||
let pkey_1 = PKey::public_key_from_raw_bytes(q_string, Id::X25519)?;
|
||||
let pkey_1 = PKey::public_key_from_raw_bytes(q_string, Id::X25519).unwrap();
|
||||
|
||||
// Export the bytes only
|
||||
export_key(
|
||||
|
@ -413,9 +420,12 @@ pub async fn test_export_x25519() -> Result<(), CliError> {
|
|||
false,
|
||||
)?;
|
||||
let bytes = read_bytes_from_file(&tmp_path.join("output.export.bytes"))?;
|
||||
let pkey_2 = PKey::public_key_from_der(&bytes)?;
|
||||
let pkey_2 = PKey::public_key_from_der(&bytes).unwrap();
|
||||
|
||||
assert_eq!(pkey_1.public_key_to_der()?, pkey_2.public_key_to_der()?);
|
||||
assert_eq!(
|
||||
pkey_1.public_key_to_der().unwrap(),
|
||||
pkey_2.public_key_to_der().unwrap()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ use cosmian_kmip::kmip::{
|
|||
kmip_objects::Object,
|
||||
kmip_types::{CryptographicAlgorithm, LinkType, UniqueIdentifier, WrappingMethod},
|
||||
};
|
||||
use cosmian_kms_utils::crypto::{
|
||||
curve_25519::operation::create_x25519_key_pair, symmetric::create_symmetric_key,
|
||||
wrap::decrypt_bytes,
|
||||
};
|
||||
#[cfg(not(feature = "fips"))]
|
||||
use cosmian_kms_utils::crypto::curve_25519::operation::create_x25519_key_pair;
|
||||
use cosmian_kms_utils::crypto::{symmetric::create_symmetric_key, wrap::decrypt_bytes};
|
||||
use tempfile::TempDir;
|
||||
#[cfg(not(feature = "fips"))]
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
|
@ -102,6 +102,7 @@ pub async fn test_import_export_wrap_rfc_5649() -> Result<(), CliError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "fips"))]
|
||||
#[tokio::test]
|
||||
pub async fn test_import_export_wrap_ecies() -> Result<(), CliError> {
|
||||
// create a temp dir
|
||||
|
@ -110,11 +111,9 @@ pub async fn test_import_export_wrap_ecies() -> Result<(), CliError> {
|
|||
// init the test server
|
||||
let ctx = ONCE.get_or_init(start_default_test_kms_server).await;
|
||||
// Generate a symmetric wrapping key
|
||||
let mut rng = CsRng::from_entropy();
|
||||
let wrap_private_key_uid = "wrap_private_key_uid";
|
||||
let wrap_public_key_uid = "wrap_public_key_uid";
|
||||
let wrap_key_pair =
|
||||
create_x25519_key_pair(&mut rng, wrap_private_key_uid, wrap_public_key_uid)?;
|
||||
let wrap_key_pair = create_x25519_key_pair(wrap_private_key_uid, wrap_public_key_uid)?;
|
||||
// Write the private key to a file and import it
|
||||
let wrap_private_key_path = tmp_path.join("wrap.private.key");
|
||||
write_kmip_object_to_file(wrap_key_pair.private_key(), &wrap_private_key_path)?;
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
pub async fn test_create_symmetric_key_with_jwe() -> Result<(), CliError> {
|
||||
// init the test server
|
||||
// since we are going to rewrite the conf, use a different port
|
||||
let ctx = start_test_server_with_options(19997, true, false, false, true, false).await;
|
||||
let ctx = start_test_server_with_options(19997, true, false, false, true).await;
|
||||
|
||||
create_symmetric_key(&ctx.owner_cli_conf_path, None, None, None, &["test_jwe"])?;
|
||||
|
||||
|
|
|
@ -166,6 +166,8 @@ pub fn password_wrap_import_test(
|
|||
let key_bytes = object.key_block()?.key_bytes()?;
|
||||
|
||||
//wrap and unwrap using a password
|
||||
// TODO - Remove not fips flag by solving #124 on Github.
|
||||
#[cfg(not(feature = "fips"))]
|
||||
{
|
||||
wrap(
|
||||
&ctx.owner_cli_conf_path,
|
||||
|
|
|
@ -12,10 +12,8 @@ use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt};
|
|||
use base64::{engine::general_purpose::STANDARD as b64, Engine as _};
|
||||
use cloudproof::reexport::crypto_core::{CsRng, RandomFixedSizeCBytes, SymmetricKey};
|
||||
use cosmian_kms_server::{
|
||||
bootstrap_server::{start_https_bootstrap_server, BootstrapServerMessage},
|
||||
config::{
|
||||
BootstrapServerConfig, ClapConfig, DBConfig, HttpConfig, HttpParams, JWEConfig, Jwk,
|
||||
JwtAuthConfig, ServerParams,
|
||||
ClapConfig, DBConfig, HttpConfig, HttpParams, JWEConfig, Jwk, JwtAuthConfig, ServerParams,
|
||||
},
|
||||
kms_server::start_kms_server,
|
||||
};
|
||||
|
@ -91,17 +89,16 @@ impl TestsContext {
|
|||
/// Start a test KMS server in a thread with the default options:
|
||||
/// JWT authentication and encrypted database, no TLS
|
||||
pub async fn start_default_test_kms_server() -> TestsContext {
|
||||
start_test_server_with_options(9990, false, true, true, false, false).await
|
||||
start_test_server_with_options(9990, false, true, true, false).await
|
||||
}
|
||||
|
||||
/// Start a server (KMS or bootstrap) in a thread with the given options
|
||||
/// Start a KMS server in a thread with the given options
|
||||
pub async fn start_test_server_with_options(
|
||||
port: u16,
|
||||
use_jwt_token: bool,
|
||||
use_https: bool,
|
||||
use_client_cert: bool,
|
||||
use_jwe_encryption: bool,
|
||||
use_bootstrap_server: bool,
|
||||
) -> TestsContext {
|
||||
let server_params = genererate_server_params(
|
||||
port,
|
||||
|
@ -109,7 +106,6 @@ pub async fn start_test_server_with_options(
|
|||
use_https,
|
||||
use_client_cert,
|
||||
use_jwe_encryption,
|
||||
use_bootstrap_server,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -117,32 +113,6 @@ pub async fn start_test_server_with_options(
|
|||
// Create a (object owner) conf
|
||||
let (owner_cli_conf_path, mut owner_cli_conf) = generate_owner_conf(&server_params).unwrap();
|
||||
|
||||
// Start the server (bootstrap or KMS) in a thread and wait for it to be up
|
||||
if server_params.bootstrap_server_params.use_bootstrap_server {
|
||||
println!(
|
||||
"Starting bootstrap server at URL: {} with server params {:?}",
|
||||
owner_cli_conf
|
||||
.bootstrap_server_url
|
||||
.as_ref()
|
||||
.expect("The bootstrap server URL should be configured"),
|
||||
&server_params
|
||||
);
|
||||
|
||||
let (server_handle, thread_handle) =
|
||||
start_test_bootstrap_server(server_params).expect("Can't start bootstrap server");
|
||||
|
||||
// generate a user conf
|
||||
let user_cli_conf_path =
|
||||
generate_user_conf(port, &owner_cli_conf).expect("Can't generate user conf");
|
||||
|
||||
TestsContext {
|
||||
owner_cli_conf_path,
|
||||
user_cli_conf_path,
|
||||
owner_cli_conf,
|
||||
server_handle,
|
||||
thread_handle,
|
||||
}
|
||||
} else {
|
||||
println!(
|
||||
"Starting KMS test server at URL: {} with server params {:?}",
|
||||
owner_cli_conf.kms_server_url, &server_params
|
||||
|
@ -176,7 +146,6 @@ pub async fn start_test_server_with_options(
|
|||
server_handle,
|
||||
thread_handle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Start a test KMS server with the given config in a separate thread
|
||||
|
@ -198,28 +167,6 @@ fn start_test_kms_server(
|
|||
Ok((server_handle, thread_handle))
|
||||
}
|
||||
|
||||
/// Start a test bootstrap server with the given config in a separate thread
|
||||
fn start_test_bootstrap_server(
|
||||
server_params: ServerParams,
|
||||
) -> Result<(ServerHandle, JoinHandle<Result<(), CliError>>), CliError> {
|
||||
let (tx, rx) = mpsc::channel::<ServerHandle>();
|
||||
let tokio_handle = tokio::runtime::Handle::current();
|
||||
let thread_handle = thread::spawn(move || {
|
||||
// we instantiate the message channel in the thread so that it is kept alive
|
||||
// but we ignore the messages sent by the bootstrap server
|
||||
let (bs_msg_tx, _bs_msg_rx) = mpsc::channel::<BootstrapServerMessage>();
|
||||
tokio_handle
|
||||
.block_on(start_https_bootstrap_server(server_params, tx, bs_msg_tx))
|
||||
.map_err(|e| CliError::ServerError(e.to_string()))
|
||||
});
|
||||
trace!("Waiting for test bootstrap server to start...");
|
||||
let server_handle = rx
|
||||
.recv_timeout(Duration::from_secs(25))
|
||||
.expect("Can't get test bootstrap server handle after 25 seconds");
|
||||
trace!("... got handle ...");
|
||||
Ok((server_handle, thread_handle))
|
||||
}
|
||||
|
||||
/// Create a new database and return the database secret
|
||||
pub fn fetch_version(cli_conf_path: &str) -> Result<String, CliError> {
|
||||
// Configure a database and create the kms json file
|
||||
|
@ -288,7 +235,6 @@ async fn genererate_server_params(
|
|||
use_https: bool,
|
||||
use_client_cert: bool,
|
||||
use_jwe_encryption: bool,
|
||||
use_bootstrap_server: bool,
|
||||
) -> Result<ServerParams, CliError> {
|
||||
let jwk_private_key: Option<Jwk> = if use_jwe_encryption {
|
||||
Some(JWE_PRIVATE_KEY_JSON.parse().expect("Wrong JWK private key"))
|
||||
|
@ -304,11 +250,7 @@ async fn genererate_server_params(
|
|||
JwtAuthConfig::default()
|
||||
},
|
||||
db: DBConfig {
|
||||
database_type: if use_bootstrap_server {
|
||||
None
|
||||
} else {
|
||||
Some("sqlite-enc".to_string())
|
||||
},
|
||||
database_type: Some("sqlite-enc".to_string()),
|
||||
clear_database: true,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -342,11 +284,6 @@ async fn genererate_server_params(
|
|||
jwe: JWEConfig {
|
||||
jwk_private_key: jwk_private_key.clone(),
|
||||
},
|
||||
bootstrap_server: BootstrapServerConfig {
|
||||
use_bootstrap_server,
|
||||
bootstrap_server_port: port,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
ServerParams::try_from(&clap_config)
|
||||
|
@ -372,12 +309,12 @@ fn generate_owner_conf(server_params: &ServerParams) -> Result<(String, CliConf)
|
|||
} else {
|
||||
None
|
||||
},
|
||||
ssl_client_pkcs12_path: if server_params.verify_cert.is_some() {
|
||||
ssl_client_pkcs12_path: if server_params.client_cert.is_some() {
|
||||
Some("test_data/certificates/owner.client.acme.com.p12".to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
ssl_client_pkcs12_password: if server_params.verify_cert.is_some() {
|
||||
ssl_client_pkcs12_password: if server_params.client_cert.is_some() {
|
||||
Some("password".to_string())
|
||||
} else {
|
||||
None
|
||||
|
@ -387,14 +324,6 @@ fn generate_owner_conf(server_params: &ServerParams) -> Result<(String, CliConf)
|
|||
} else {
|
||||
None
|
||||
},
|
||||
bootstrap_server_url: if server_params.bootstrap_server_params.use_bootstrap_server {
|
||||
Some(format!(
|
||||
"https://0.0.0.0:{}",
|
||||
server_params.bootstrap_server_params.bootstrap_server_port
|
||||
))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
// We use the private key since the private key is the public key with additional information.
|
||||
..Default::default()
|
||||
};
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMDCCAhgCCQDAPL/cC9h3iTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJG
|
||||
UjEMMAoGA1UECAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRl
|
||||
c3QxGjAYBgNVBAMMEUFjbWUgVGVzdCBSb290IENBMB4XDTIzMDUxOTE1Mjk0NVoX
|
||||
DTMzMDUxNjE1Mjk0NVowWjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwG
|
||||
A1UEBwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MRowGAYDVQQDDBFBY21lIFRl
|
||||
c3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANYf+HTZ
|
||||
AXLZaWj43qRTqdKs0piG6sk0oY7RFyE2/+KE6nArFPo70pAHgrzkiabPL8gGPxyL
|
||||
wTxS+So7crRKNDeGsaHcejxJyh6ySq/4CfWuO7ZBIFU7m0Di4QSWbJyMDPLevaFn
|
||||
+oBL2x+8Zs2oIFL5kYdx/eMY105IlNUbgIoGoQMww+mF7CsAZ8YPlVrXTWT9Rmer
|
||||
p22dwX9oGzY5Fpi/KjMDZlwZ4sIKnK3RdKSf0jbonnVB86rNyEU+zglNHIhnYaOc
|
||||
u/gJ9fJzluHJz0MSgMB2cOh6O8ye1sOAN/U+XgBv4tlS1I2bV9dlBhpfjCyjDM45
|
||||
TdLtiOtoVmIyORkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAxIxqxn/YAGKBbgZW
|
||||
N7ZLF9iCEpmocYzwTn05mMdh5ywwMPJ908lVdUv+JfPXUNFcar/8iH/WOyehw0W4
|
||||
+ceLqIYZaGbEkYDDuje/INkYsOrWBRwa6rPJh5jENYCqEOeQn39/Ei6TScx0/m78
|
||||
+UfHYZRcO6v2iXN3PMezb780bU1ChruIu0X6U4iHD1i9GS9u1rhUHCacf0131i3o
|
||||
YOmBzbbV6ZV5FkwEjICJi/a1PnMauXmX/0jaX8i7Y1dXTNtYvmki7KnNZE50Qhd7
|
||||
ZgMmZdGGqfYCfs9ilSNZIu8EUoXZEYGC4S1gjqoh5YebCLO8qJTRDpR2JQWLkHlv
|
||||
x/zdVw==
|
||||
MIIDlTCCAn2gAwIBAgIUfDRrRInqLZKVabmBD68XsqmlpPgwDQYJKoZIhvcNAQEL
|
||||
BQAwWjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwGA1UEBwwFUGFyaXMx
|
||||
ETAPBgNVBAoMCEFjbWVUZXN0MRowGAYDVQQDDBFBY21lIFRlc3QgUm9vdCBDQTAe
|
||||
Fw0yMzEyMDYxMzI4NTJaFw0zMzEyMDMxMzI4NTJaMFoxCzAJBgNVBAYTAkZSMQww
|
||||
CgYDVQQIDANJZEYxDjAMBgNVBAcMBVBhcmlzMREwDwYDVQQKDAhBY21lVGVzdDEa
|
||||
MBgGA1UEAwwRQWNtZSBUZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQCo6TwveDxbHYNEGgDnTQHtfPFFKbMsoJpD1emGwNMLsFJgfXLo
|
||||
mLPnv690cbiE44aEAFl6cjLoizluhT0Ue03I2uflOT+JCeF3HSBLdd+VQcmSgWQD
|
||||
Mnawd4j7H83KinWtWZaYK/MntYrMExKNt7RoaCZjtOo8RU3G+gY3aK8l5U3TUMHQ
|
||||
kplaNXVMHfTnrAAaTh2RzlfNF6Hy7bgvkncnwuyMeZHzbfxtJ/XBp20cIQL50T48
|
||||
OOzzN1jiTsIMnDndGqT8/AcJstjC6seXG7RPb+O1iP7eQwLIKEAfLls4p6KsQW+A
|
||||
MI3oxKJviOxpyk/623B6rQ30G2Q3okZnipqtAgMBAAGjUzBRMB0GA1UdDgQWBBQG
|
||||
UrI84vawMQ/sK+qhnG6PvW1RDDAfBgNVHSMEGDAWgBQGUrI84vawMQ/sK+qhnG6P
|
||||
vW1RDDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCa2m7/d31p
|
||||
bwwLaD7ij5AWDYH7tAEw8ay3GRYj2Cx8VfxXUrsQLb2pnrFGZKnjIcyrDTfJZ/tM
|
||||
mSZSiplhjrYZ+ubs4+Hxzslzi5Ouu86VJIdiPTCp4T+pQR0RMGs4Dc71r4zYz8pG
|
||||
ym4C5umQI1SkwnIJxPkVSu7FQxt/dzzMUALblvEFa9F0Fl0OzZlgXGXIcrOaAayW
|
||||
yCQuhfhMHnWo4ogh4maPnWiSR4vnG0FIMcM8oXPMO2kL7doUk84fAZJu5gglOAPW
|
||||
kUWxJiaKo2oX5k/yILww9MC5MptMJ51mHk9O4IKE+PXJ0Jbc6UlTzPOkwT6aoo8p
|
||||
kwpPcggYgoUl
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDWH/h02QFy2Wlo
|
||||
+N6kU6nSrNKYhurJNKGO0RchNv/ihOpwKxT6O9KQB4K85Immzy/IBj8ci8E8Uvkq
|
||||
O3K0SjQ3hrGh3Ho8Scoeskqv+An1rju2QSBVO5tA4uEElmycjAzy3r2hZ/qAS9sf
|
||||
vGbNqCBS+ZGHcf3jGNdOSJTVG4CKBqEDMMPphewrAGfGD5Va101k/UZnq6dtncF/
|
||||
aBs2ORaYvyozA2ZcGeLCCpyt0XSkn9I26J51QfOqzchFPs4JTRyIZ2GjnLv4CfXy
|
||||
c5bhyc9DEoDAdnDoejvMntbDgDf1Pl4Ab+LZUtSNm1fXZQYaX4wsowzOOU3S7Yjr
|
||||
aFZiMjkZAgMBAAECggEAWInxt4c/tRi3IIO/tB0wHH//uLgY/0e3AhHtSXuvhR/G
|
||||
vMjjrLDt2UZxxd+OF56WOFR05j3XkjUQ+GiKfogsXUVhz/cVyDYO0HCSt36Nx7va
|
||||
zvrQ/s1d3g+yUa5NjNHQTODTcplHGKPFILNLowBBFW5Cwcnd3HiaFrGmcRQlK2zd
|
||||
+cie78jiy8BVm6oOS7Bi+FeagVDOolPLm1ZrpLW65iu3hzz59nrpTezRck/LrDD3
|
||||
LU6HLMxtGY0cjaHreR3aXaTM6CZyESw1tdo+LXuvTtNwU9DENd6lbYuCrOmDOkxB
|
||||
IRkTuSOdsn+swWRoP27tqEvwBK/QG5fp5E2GXaMMzQKBgQD+s7ATmXS6T8HqaGX6
|
||||
Xkwlhmtb1PAXzrbhMVqCrADsooWmLraW8rKQjA6YkSu7UfD9TkXMGto1M2Z9lo4l
|
||||
LQ0xVvW2CL4y395YHpo35bWckhYuqn8m8WOkI9p3SDhTnIMOMymfduE2h+3JWcAn
|
||||
jottsG9+8sv6EOdUwZD7EdwFewKBgQDXN1drCQTmH9/KiYIst0XbXxa/8yTppdnG
|
||||
J5+DEOZF3mTXfVGbd/s0PNKiqDQKbwbh2SygsCEyKYC4vZLmq7MDtmNL5kLeTvzf
|
||||
6Flk9SpEj1kKOxAWLlgc57ivZdqGSUM9Aj2v6tMeo84eEp6D1tDjLP5RdSNjgIAv
|
||||
rwAACXGVewKBgQClI+Q6EPk6A5R7Y40bNCCzA+B//iRdi03P3KwOpW9D/mwhP5Br
|
||||
dpiIWAburNFp9ssFscZXe+GXNOhy7Tbkq70uDG/rwudvHO+QuubK70k9Zwqy3yDq
|
||||
IwCz3/s5871xmLzwbAPEvNNxA9kNAAAypZ2JVSg1az8NuAAFWCukXgQGGQKBgQCP
|
||||
klO3C+VAv7LDosg8nGb12ZGLq+DMHeAR2Q0ImpWDtsD/IJL4bCogxxKdgCh3bWnh
|
||||
8MdcyyLaG+XLWGxPhet+ZoYHdCzXsUnw9UftmcAAzMBRmuU4ZuJRJiSGniQRwX4h
|
||||
jQUp/jWpEw3F8hXdTck8RB/Ep6hcELVzGgOeAq7LUQKBgEXSfUdMw1dAXbl4DUGi
|
||||
qJYIABJfTp8xp4Pgo3tHYTtIPBkqm6BoqPa0UsiRwLJm8+t/5iO3/nFv/9xL2wBg
|
||||
rq5678GY52Kn5XfZ7ubEYRD/Fuga7Et03JN3m7AdIS6I0I0sFh9T1dF2WljfrZ8m
|
||||
V6h8iJs3X6F+7MGcID9i0l8F
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCo6TwveDxbHYNE
|
||||
GgDnTQHtfPFFKbMsoJpD1emGwNMLsFJgfXLomLPnv690cbiE44aEAFl6cjLoizlu
|
||||
hT0Ue03I2uflOT+JCeF3HSBLdd+VQcmSgWQDMnawd4j7H83KinWtWZaYK/MntYrM
|
||||
ExKNt7RoaCZjtOo8RU3G+gY3aK8l5U3TUMHQkplaNXVMHfTnrAAaTh2RzlfNF6Hy
|
||||
7bgvkncnwuyMeZHzbfxtJ/XBp20cIQL50T48OOzzN1jiTsIMnDndGqT8/AcJstjC
|
||||
6seXG7RPb+O1iP7eQwLIKEAfLls4p6KsQW+AMI3oxKJviOxpyk/623B6rQ30G2Q3
|
||||
okZnipqtAgMBAAECggEAKZLig+KJpHmCngfycfvDvjLS5Y2KcrEC1zB23npmV4mp
|
||||
9OLbngE7wo4s/rGg02B28tVtMJScEB14YMn9iyWAMzAiBIrPJwkeC+XI1ZnpEoET
|
||||
PnKHbbwFd5CsT/b3fWMP7L9QsBqdKghmZa1KE0SEbHA6Bq94OaZrKs7OKeQju+Uq
|
||||
PaSDnCumAPDUKdgSthnUOywgaCzAufnnmQoxhFlbtOBfO8C1fbCCgLp2KK6bT/iY
|
||||
AVI3IxETmM0bFFHcxyt/KoN7KubnzBvWkRPHiCWfA91u4YTvYBi22dpnIjaglXIu
|
||||
FYek0cCYUkvQm9YOb7Da57qPPT3s0SNEtjQIgOG5dwKBgQC+h+dC9Chj9/ydVcpM
|
||||
KIpCvf/2eWQOjNccD8wUdB1rlbI72JJiceaYLCFdcjMsAO3Ke6C75qReBcJkTOfS
|
||||
rQ1IbuD2luTzWkQTAosQ1HS0h5oWa0zXlDj7GJtBZh2je6cv4O1qPEkX4OCGmfOE
|
||||
AxVHBBsD/jgAsefMifL7IuJ0RwKBgQDi84psRg2Z3+dUraDB6BfSwQm3tgXsHGoM
|
||||
ENN335CQWQyJ0WIvutJSRt3fdrayTT/WkKS40D2NpuSldk3+MBvmaIaEAqjyrJ8Y
|
||||
dEr6MAWX0BSrUd8jSAm+xHTI4VUrr/nMVST9leaWRgm5NE/2PYjJUE1EfNHUgy6i
|
||||
pTzbKPF3awKBgGn2a0dxQoVWhcd6zudMJJi50oDhQiRVb8zLfFRjv3j16AogiEj3
|
||||
z6cR4/x0ZsEyQw05dEsMGp2v1kyx+LvSQnDmOXbqtKoiqXlpEK5refxs7eVKB5Jd
|
||||
fNMo/C+C+zjQrEqUbXWH0Z7WEgjJ1gS1MkAsqFmwKLU6PBAlKF1DKW5BAoGAOmVN
|
||||
5cQ0tbYuENTIO3ybvKfc9z9H0NQS2V3u+7YzvWCcYE3XBM7+VRtU9a3XHpPP7Ea1
|
||||
i7RRUkRyKr0BHnmEhEm66vbAQAj4utMZg7ydg82Ps/FSCAL+Nu7X2eRZBO+3x8LU
|
||||
zMcoWNxWnif+ty5oJtyZtRik6RiEBGed/ApR71cCgYAp/rTtwNS02Y5gxjSSZYON
|
||||
M3LLJQO4iCZrhY4fZOIcZTm7Se6ouIsW5DOd3YavMb9VcKpwNCn3ZybjOEPDSTVR
|
||||
WTyf48pVIXJesMyno557A+RtYXbN5pYSkbI+CUUNKjll6Rt1Bs/tEBSXKkc6GO+5
|
||||
V1xAZvTW1jK3LpqH/QuMyQ==
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMDCCAhgCCQDTJGaQvJLD0DANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJG
|
||||
UjEMMAoGA1UECAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRl
|
||||
c3QxGjAYBgNVBAMMEUFjbWUgVGVzdCBSb290IENBMB4XDTIzMDUxOTE1Mjk0NVoX
|
||||
DTMzMDUxNjE1Mjk0NVowWjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwG
|
||||
A1UEBwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MRowGAYDVQQDDBFrbXNlcnZl
|
||||
ci5hY21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXnnzdx
|
||||
N48j28FJO+HNpeswAZSriNQGAtvd3fiak/MeZ6VbIjXgGIZ073r9aNYsOxkIR/aW
|
||||
HVBDcQBsQqUfP+Ni9E1Qfw/Uav1CqnZszAaX6BUJ1bRzT0WfYMgnjiNnqJPf2FAC
|
||||
XvdifjB8fiEBfCBUZ8BuiqTYWVTnBLC33oLpJAn57oUgCUnbNS6WNCQfmO5sIFdd
|
||||
E3VwfOxeOxFsJ5pCVSJu12zJACJ6nNjbAt3jdVBnix6tN8iuQM8jlKk0NgGqRu9F
|
||||
VxZ0/USwSnTW2bXKmk2xgVF1SxdNC5EWK0H7PbF+P5CSWK17KtAVTGQhH9BI6EcZ
|
||||
8Z8hDewPDECnXBcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsNO3wkHT6M5qG7l7
|
||||
4YL+4K+dm8TB6waUAmGIuDcnQ1uO1iSIkYl9RQG545O7WjN9qozvLg45lBdecLAQ
|
||||
27J8F/tOnIw6hpTuUdBN4NGNH5RN5z6rsjZLevuRHulRAgHGUMnmBGb9jDiIm63f
|
||||
e0YF++xS3mW4viCFRY8ECJ/43XNLxejp7ZAZUkWaJnRhTi7iSNd00ENjKwSsX0UC
|
||||
KlhwB2Jkrs7QDS6OAzAb05r+VjeBkgpBaimyl6mHSrrbUz086A/vn6U3l33QiTVP
|
||||
EQwLQ3B8ubLLPy8hs/RVWubr8+DZ2lRwy2cdzqKhZT816uWV1Kk4TsPfLl2FgQ+G
|
||||
JfbZkg==
|
||||
MIIDOzCCAiMCFHvc/pbd2xt7p9gk+cPUiP6O+TL+MA0GCSqGSIb3DQEBCwUAMFox
|
||||
CzAJBgNVBAYTAkZSMQwwCgYDVQQIDANJZEYxDjAMBgNVBAcMBVBhcmlzMREwDwYD
|
||||
VQQKDAhBY21lVGVzdDEaMBgGA1UEAwwRQWNtZSBUZXN0IFJvb3QgQ0EwHhcNMjMx
|
||||
MjA2MTMyODUyWhcNMzMxMjAzMTMyODUyWjBaMQswCQYDVQQGEwJGUjEMMAoGA1UE
|
||||
CAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRlc3QxGjAYBgNV
|
||||
BAMMEWttc2VydmVyLmFjbWUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEAi5cvrpnkRBNPl9KZvpfDpZEbyiPBYymXFw2tAoAVozy6lXwHGJMGROY7
|
||||
ML28gOLiZZdQ1VQDjsip1KxwQX4IJsXWbLTEV5qj267xfhsjgaeXWVjdllY7EYK7
|
||||
AjtkWOuNw+unqQDdTRpKovd5/dDHZJjOBXJWPjFu8YMug2ua9pLQzad2D6Eg2bkr
|
||||
Hp0DAXipDZC84DAEmbJyrZrSkVKiy/A9HEzUjv+2zv3yXHIAXAGJp3XHMrNxiORY
|
||||
HYFKpawhNrPfzXCLCtYkAtWPmU3d+jNkbeY0QPiu24vbfkZnX+kXSmJxTDfzFE0m
|
||||
1JrgHOzB7yxGCeKPdaJMlkaTIIcxnQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAM
|
||||
WLbwGpbzZC1lH1PudMTB2dEsjgjZISb5nP/DnKToIqoVhVt7k8vBaos5jNKROGl6
|
||||
wvv7e/+5mcvBqJp/uIw1vkMr9sIf7wYk9tlOrUlOkPH/7f9yvcPBpcjUfMXiiMzG
|
||||
aF9o+kXfrMcA8olSczcaodA7soRqQq4a1aBYl29Z1U+VoqjpdoD4KKCfOskwH3vQ
|
||||
5Q+xfQ04G6alRss5sSuU107osyCGtvJygcagtGkr/xr2ZlOhZnsJNLKwidm9Nshs
|
||||
MAKl65UTYM3j/5JfCF1/9kRFfZiwmlH2rGWsTqRtjka4XkVy47qnW5Q0iFDzHgKE
|
||||
N2PGxEjdRC6CRAuQMs9+
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICnzCCAYcCAQAwWjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwGA1UE
|
||||
BwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MRowGAYDVQQDDBFrbXNlcnZlci5h
|
||||
Y21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXnnzdxN48j
|
||||
28FJO+HNpeswAZSriNQGAtvd3fiak/MeZ6VbIjXgGIZ073r9aNYsOxkIR/aWHVBD
|
||||
cQBsQqUfP+Ni9E1Qfw/Uav1CqnZszAaX6BUJ1bRzT0WfYMgnjiNnqJPf2FACXvdi
|
||||
fjB8fiEBfCBUZ8BuiqTYWVTnBLC33oLpJAn57oUgCUnbNS6WNCQfmO5sIFddE3Vw
|
||||
fOxeOxFsJ5pCVSJu12zJACJ6nNjbAt3jdVBnix6tN8iuQM8jlKk0NgGqRu9FVxZ0
|
||||
/USwSnTW2bXKmk2xgVF1SxdNC5EWK0H7PbF+P5CSWK17KtAVTGQhH9BI6EcZ8Z8h
|
||||
DewPDECnXBcCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCYqz562+BqLIYo6nqU
|
||||
EOK4EsPmAmaDmHbosk6c3qADSvd8RjLyPHxQRvgJtbOZD7zAEdSdO6hnejU0D4Cw
|
||||
hYi4pQ6z73UwnEtLNdmXUmDYBl24g1iVKktgcJbxjXBuK5cMmEAiYxF/ZR4MKapi
|
||||
2gtDwSrfLNM87zbBy9N3Cc6Yasj0DHq5dUyjm92PjYSw/mzwegK1feZJ4GfUVN6+
|
||||
FQ8jxQskthPtIm55pTox7XMhQbKTNms8UT6LRb/yY0XZq5jtci7cxEjv5gRmWU/I
|
||||
TigNDgVHOsRzVwbQhM8mPe7rK6xtJJeyDGolzUY2mLwkPIUlnLjS7O+6SJt9L3ZR
|
||||
S2Sz
|
||||
Y21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIuXL66Z5EQT
|
||||
T5fSmb6Xw6WRG8ojwWMplxcNrQKAFaM8upV8BxiTBkTmOzC9vIDi4mWXUNVUA47I
|
||||
qdSscEF+CCbF1my0xFeao9uu8X4bI4Gnl1lY3ZZWOxGCuwI7ZFjrjcPrp6kA3U0a
|
||||
SqL3ef3Qx2SYzgVyVj4xbvGDLoNrmvaS0M2ndg+hINm5Kx6dAwF4qQ2QvOAwBJmy
|
||||
cq2a0pFSosvwPRxM1I7/ts798lxyAFwBiad1xzKzcYjkWB2BSqWsITaz381wiwrW
|
||||
JALVj5lN3fozZG3mNED4rtuL235GZ1/pF0picUw38xRNJtSa4Bzswe8sRgnij3Wi
|
||||
TJZGkyCHMZ0CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAKJxvuFTtG1/ZU4EnS
|
||||
6dTnhE800F1hhzSk89T0/zv4Fkv8HzvEKU897e7M8yhPzUDo9NZoEb1GiHiDWjiM
|
||||
mTALy25S2nfFFOghnMhhXnpel+z16MoC7vsjqdjAF4DF6cJ0Qx8OV1hG82NumEd5
|
||||
s4UGJbrAd5tpGZ+jddmOoxm+hltqW7OChxWrzm7Vh25n70wjP/SaN9joOhlIxiGH
|
||||
I4Hr4Bqx2ljcadWFHV1u12szrOsvJtEmYZtQHuvht/N1BAyytRKNZiFMjlSgdPLF
|
||||
nQ4yeJ49RN+E7OYfuvyspmMjbVe/0o80fk1d3TOKn5YTev2S8G+7psDRZlHwrU/o
|
||||
f5pM
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl5583cTePI9vB
|
||||
STvhzaXrMAGUq4jUBgLb3d34mpPzHmelWyI14BiGdO96/WjWLDsZCEf2lh1QQ3EA
|
||||
bEKlHz/jYvRNUH8P1Gr9Qqp2bMwGl+gVCdW0c09Fn2DIJ44jZ6iT39hQAl73Yn4w
|
||||
fH4hAXwgVGfAboqk2FlU5wSwt96C6SQJ+e6FIAlJ2zUuljQkH5jubCBXXRN1cHzs
|
||||
XjsRbCeaQlUibtdsyQAiepzY2wLd43VQZ4serTfIrkDPI5SpNDYBqkbvRVcWdP1E
|
||||
sEp01tm1yppNsYFRdUsXTQuRFitB+z2xfj+QkliteyrQFUxkIR/QSOhHGfGfIQ3s
|
||||
DwxAp1wXAgMBAAECggEAXX6jfnYiTltx64Je6cif+WNrcKIekQX2NHvbLM/IEtmO
|
||||
pWQvalco2xUpJJGMtC3m/Btrmq5MRMBM/WUFRdLPiVBpxuxXPs+Bn8ojEGwNqqWO
|
||||
19RcB7537Q99Vi7cbl1rZjJez/AWHqn13VM7LVSN5BZNBegF4BJAfZVXUlO8ZN8f
|
||||
6hxy3hBtAxQgNlGL9xemz1hjNWrVcelKXyAsbff6OpjmJDpTcGoRqopFbABzFAqU
|
||||
G9jPG6/C6tG/R3YDYK/YRsJLHHEMEaXTi+U35DY+XHJyFPc3YeAZzfVZKo44gD5+
|
||||
mSTw/g1XP8IUT36zUV8tIxfc+XCc2No+iAkL7Wl7GQKBgQDSG28bajXtpxPoSNQt
|
||||
2Hx6qp8uUH1uZfxtM+jpjjJTqPbnVZw68xFR4EKBrePEC8D+Q92vOzY35GIZtHXN
|
||||
sRY2+6RahWMo2SACZNKu58BFXzDDvVIpgSye2Ys7RnmGdN5AeKQgSm+D/E0cDxTe
|
||||
nYaEXzAbcTl1vuEor1fvmIk3QwKBgQDKJIWln8uxL45EJ2E7SDj9vEgybbHbPtTw
|
||||
y96ahVLEFhfKkCX257y564xp8vQXTRZh57D+jKRjvE/or1RAYEEI90v3hs604rCZ
|
||||
S4/BPAtlH41yq/NgQy765i8PR0SrTLqDzJCbJXVzrbY/JwMVuY40CUb9sXuLu2Fm
|
||||
R0Zbo8oonQKBgBNWkxNi4zPMfPiUO3M8ybhAnAYXQnQ2ztT+QiG9BMTOeGsyZf7H
|
||||
AIEYswZciuowasL8XBsUyBi83IqhIXadJf5JiwcJ3+aSlW+i+AFBM2EvMb3SXw2S
|
||||
5hh4zWfXRLgraYllkTWnpDvxrOc4PCOBPDBS0oq0ESXVO8QS33UeBQMhAoGBAI9P
|
||||
i0zb2G57F7Kr9Jwx3O3PEaRm7sRQbGl3MA9+3CnWu/FJdxDwRHXPUFJBA9qNNYQd
|
||||
3fbpwRZQiJqfyuyFETaJFNudQGkvmiJkVruZlT6ROxgEXlxt5R3OGakMTtvfXxBX
|
||||
9GF6EiX8DwwA3YgGcJHlzeXIcZ2kMC5x86i+m3FlAoGAYbkjhKImWbiBOgKO8of2
|
||||
UZes4rFbtuDHETYydT8sBtHlMr97waT9NMSOWZpii+G1QavrjHISUDyBMYb16heo
|
||||
50Q4JjWPH4rCC4ZW9MR9ZxWz08HpRfw3NILTYuoz2EpxDUg6/Bo6QcWu7uYizZtZ
|
||||
SshHT3/UcgNshMetjpwveqQ=
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCLly+umeREE0+X
|
||||
0pm+l8OlkRvKI8FjKZcXDa0CgBWjPLqVfAcYkwZE5jswvbyA4uJll1DVVAOOyKnU
|
||||
rHBBfggmxdZstMRXmqPbrvF+GyOBp5dZWN2WVjsRgrsCO2RY643D66epAN1NGkqi
|
||||
93n90MdkmM4FclY+MW7xgy6Da5r2ktDNp3YPoSDZuSsenQMBeKkNkLzgMASZsnKt
|
||||
mtKRUqLL8D0cTNSO/7bO/fJccgBcAYmndccys3GI5FgdgUqlrCE2s9/NcIsK1iQC
|
||||
1Y+ZTd36M2Rt5jRA+K7bi9t+Rmdf6RdKYnFMN/MUTSbUmuAc7MHvLEYJ4o91okyW
|
||||
RpMghzGdAgMBAAECggEAG/u48VWkbwk4AYWUkKK38+79FS7Jy+lAgryZHFE1BT5d
|
||||
YS419fUzYoiNAR5oNaZGIHuPFtT6yZrsgNf4wQhU9gDfFXe/jJhRlO6jNtaV7Z39
|
||||
N0obUdIDkWUVvELPwQunpckOGVE1DAnjQHxAFmPONRp04p6jL2CVjxDvOCVQMXG9
|
||||
YcebtLfeUtjbCRjYV2hLwoBJFHRd/mRluSzhhpgI/V4AG0qEVyqg2UGht78p+NGd
|
||||
AgGvsn3uYKHtvsz3fG6R+7tMvnjpsKULHHJDAS6upP1mMaSJksdvG4xW1T+xpUmd
|
||||
XLxDc3pFo/qsTuUiSd9iFvqIvN3AqM4ewqBvDkwYAQKBgQC6xxhPQ7wMvMUhVt3I
|
||||
/BsqqmMyxQ9pnI1fXap6TYZyI+61UI51aT0by2tc2NRkmz13zLyu/qxvd5PIdGhe
|
||||
KUtxmf8hDUZaTQJq0CQMBvKmLqLZ5q4wIRMzF17/D7PxXyj1mbwgu8ZGYdWRRW5U
|
||||
SYxZv+ARKM33GDjC0FUBIq9onQKBgQC/Ux4lWSI+HByl8AuU5W+Dtf1/GgwFIX9A
|
||||
fOZG0Ot96IXE4Iq+DEEa10DX0Na+yca5H//zD3raCJRJB/BPe9S7uejDFLMNmS4a
|
||||
DPtV6JrmWjKFKzux1NGcSbNNpoYq7QG0/kl7eeybJ8N0eztVA1E1g/gm3ILkYuRY
|
||||
EhvIL5YdAQKBgQCjGO/1Z2RyivRo5H3O37apTxhIYSPQSVB6EkSnf8MDMLVlxu5f
|
||||
QIKIHt2lugHdyGGolzO8a88Plw+JX30znEOw85SBvCHPAKg3tYGErxx8WQUD2hgJ
|
||||
Fxi46JOfjorHHx2ZOaG5w76j/xKLRGHPYFoalR6IXWVde9004M8ZqrwZUQKBgEFm
|
||||
Jg3aNAxLC7flH/BbpQy+rtI9kxJF6vueNhDK5VR6oQ81OffQtIh6P94FswIwcs9h
|
||||
EtqA1hulhxqXrhtdVtB8sgXNE494ZvvcqCUrh5dqCY7fwl39Q1FLGBFY9M/DiCvY
|
||||
KEIe4TQAGZ29agCbS60hWTffdJag/zDjr790FLoBAoGAWotPJORbzfNJqA+tp4Qf
|
||||
/n4FUq0aiyEJLwUFoo+nbqAQaYv0oDpz7hapgXiv8rsoTr6l+ENi3n+yclDFGUAg
|
||||
zY/2cam9xcDI+ugwnqYo0sx/3LYdWULACJ+ayBTRrQNFTE8V2Z7fQ4OSIMunm40P
|
||||
kCYoIRGbQttPddxhZqtLD10=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDNDCCAhwCCQDTJGaQvJLD0TANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJG
|
||||
UjEMMAoGA1UECAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRl
|
||||
c3QxGjAYBgNVBAMMEUFjbWUgVGVzdCBSb290IENBMB4XDTIzMDUxOTE1Mjk0NVoX
|
||||
DTMzMDUxNjE1Mjk0NVowXjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwG
|
||||
A1UEBwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MR4wHAYDVQQDDBVvd25lci5j
|
||||
bGllbnRAYWNtZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCU
|
||||
x6zAfpMuhi1mBkD1WJdLMEltK19rE8av/PZHZMkt57W9vL1V80HU1OLoc28t8UTj
|
||||
sGGflZ9XDDZltpQ6Z63cjEuDMAtILzqHCzLCAjziu/9M9KCpLtuRJDI3aw5Awm88
|
||||
2szH8yTQ2M+sxxGpnDUgKUqDSAYTfZDtUbl+9sr/uXxPVn2gYxvumOeYyKEla4Ix
|
||||
vI8QLQk+QozB7uY16CeVmB33v1dl+fnjU9wq4Q0aHaD3oVr0spfrQgrkrWdz7O7U
|
||||
GmrhMROmm0IEBWQWIYCBTM2BiuYkzxrv6ywJqhzpCpsordFB49YVd5JleuYsObRH
|
||||
4QUMd4Vr2iJamUnsChjdAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACmpFxOcZSUM
|
||||
lvHcUw21waP8Lad1G+XUHGLcddWLysBYzlIDVqSIvLfEqA1m1i8wtwsvfxPUIgRr
|
||||
wZXEhn77YHsElisTz6ejthivYwJ2kE4qkbPndi0Vaq7AX+K3V7cw37KEoueIpAMg
|
||||
uuW+m+BuWg7feyWs6nYO8eZbdWtRZ9BddPWZb84BATeYBcuAhZ6PBX89QmqldBHw
|
||||
2qu96PS11ZbIenPOQwh4M/BHkbScLaJqRPdg1/bUrMSeP0H/2+uykpILfITXJvQz
|
||||
EQsim98z0YtN3ZjTg6zL1p2NsHf8lyqljS6MpJ+5iN6zptJenpI4V1LhhR8Dzf5M
|
||||
Ei9r97Wcoyk=
|
||||
MIIDPzCCAicCFC9Nqrnxbcu0Bfr7MfkIFOdpiRJuMA0GCSqGSIb3DQEBCwUAMFox
|
||||
CzAJBgNVBAYTAkZSMQwwCgYDVQQIDANJZEYxDjAMBgNVBAcMBVBhcmlzMREwDwYD
|
||||
VQQKDAhBY21lVGVzdDEaMBgGA1UEAwwRQWNtZSBUZXN0IFJvb3QgQ0EwHhcNMjMx
|
||||
MjA2MTMyODUyWhcNMzMxMjAzMTMyODUyWjBeMQswCQYDVQQGEwJGUjEMMAoGA1UE
|
||||
CAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRlc3QxHjAcBgNV
|
||||
BAMMFW93bmVyLmNsaWVudEBhY21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAPR/B6l2zRUk9PrT2Td6hBVF1RhJIDOdlhWD+H++qZgkfdUlajkV
|
||||
/1VxPmAcTLQaWVWgDEtWKwe7vtnmf5gFLeE+5HczS7+d+15YHBfKe1d9RL73mC+j
|
||||
17GZ6Zi3uQl5FkKXzIPeFwv9SA+d2IXs+wVaweGst48MNnLnZW0JX+B71Jw0yGry
|
||||
wvORJcCqBMOKUBp0ILRbUJLOWBs5RVcHWuvJqILARHaDxMVmmmVO48zvBtNaUT0Z
|
||||
o9znF0Rfc/BcfpJmrsXaZNj6bDk44iqL5BIt/3u7r/tVHVPmTQ4ETw8OMTlJejtU
|
||||
IjPmAGayXexACAWsy18WCmvpRIVM7Xr3Sb0CAwEAATANBgkqhkiG9w0BAQsFAAOC
|
||||
AQEAFLKbgkPVKD79lWf1/S56BJ0TgwX+YR5ASZfdpSNt2TOheAF1aezOAmF+lCsV
|
||||
55lJbrNPUZmTQxM2mBTB7yeIk/pGI5hkXJZ/35VyOVswlCSW1dfXDh4p5L6W0sek
|
||||
bx0UlLEKXw3ZI+8RqonshLG6ANu69SWLllOLmMGHdUVKPERJwQ9TdI72kDi5rU2w
|
||||
ERZxcgAcTO7qFwhlvqyZSn+hvvGny+0bZeUnrJM273ob83fyRWVxot30TjnvNsgp
|
||||
P/Hgkube8MT9i4rYS/xjZV1QP7AjQUESAS849J+KQ34+CJ91ig042imBtm4aMuGs
|
||||
ZuuIvtVDySUk7QSviiVo3DZMXw==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICozCCAYsCAQAwXjELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwGA1UE
|
||||
BwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MR4wHAYDVQQDDBVvd25lci5jbGll
|
||||
bnRAYWNtZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUx6zA
|
||||
fpMuhi1mBkD1WJdLMEltK19rE8av/PZHZMkt57W9vL1V80HU1OLoc28t8UTjsGGf
|
||||
lZ9XDDZltpQ6Z63cjEuDMAtILzqHCzLCAjziu/9M9KCpLtuRJDI3aw5Awm882szH
|
||||
8yTQ2M+sxxGpnDUgKUqDSAYTfZDtUbl+9sr/uXxPVn2gYxvumOeYyKEla4IxvI8Q
|
||||
LQk+QozB7uY16CeVmB33v1dl+fnjU9wq4Q0aHaD3oVr0spfrQgrkrWdz7O7UGmrh
|
||||
MROmm0IEBWQWIYCBTM2BiuYkzxrv6ywJqhzpCpsordFB49YVd5JleuYsObRH4QUM
|
||||
d4Vr2iJamUnsChjdAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAUBbz0xfbqAIX
|
||||
pi5ngW7kHLszgkTpoPPaq828iGCHvyNsmkZ8ZYm9dnK82nhYoxk6XlmrfIfVzalt
|
||||
WyK2k1tui5WhEarMn6xDSLHV1RBlLR1a3vnrmYkDEF1hlOmEu12X3d1RVUeS39DX
|
||||
nWB/oXq1CD39g0jV8WkOnrqHcr75JVTecO9qloFjHaEP52wXSyM2Ty6DDJhmihPA
|
||||
nVmp6S70/WOWLlOUgxV0lBac4N4Qi6dac2MRxZZsSmISzA9TzKW/Pl/eYXXM5k2u
|
||||
BRISXoQQWK0UOBeQ5vITdfJEnqbC5l90VqF8aKLKInfYtyJKVYxBdwykw5xQGJWK
|
||||
5ZuwVtbE0g==
|
||||
bnRAYWNtZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD0fwep
|
||||
ds0VJPT609k3eoQVRdUYSSAznZYVg/h/vqmYJH3VJWo5Ff9VcT5gHEy0GllVoAxL
|
||||
VisHu77Z5n+YBS3hPuR3M0u/nfteWBwXyntXfUS+95gvo9exmemYt7kJeRZCl8yD
|
||||
3hcL/UgPndiF7PsFWsHhrLePDDZy52VtCV/ge9ScNMhq8sLzkSXAqgTDilAadCC0
|
||||
W1CSzlgbOUVXB1rryaiCwER2g8TFZpplTuPM7wbTWlE9GaPc5xdEX3PwXH6SZq7F
|
||||
2mTY+mw5OOIqi+QSLf97u6/7VR1T5k0OBE8PDjE5SXo7VCIz5gBmsl3sQAgFrMtf
|
||||
Fgpr6USFTO1690m9AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAVHsjfGbzlq9w
|
||||
J6eAmgZYLdYH/fip2okie7Wxcs73VvJ4jI/ccCnQwuzybPa6oBeWfHoPpnOjDh1c
|
||||
qn5bTS29VXOo1OIf+TknJdN5VvcNrQsKY5Z7tlaLG8KYoPF5i83J5JuAtaDtl1p6
|
||||
yflW+RFRyPYtfeR0EgL0H1meeri710z/ZzLwoEuasbjngen6KxNdfJ3ET9UmgOa1
|
||||
ItG0WYzu5zcs77kH3GVSenJcKXccz9nel7S9XDaXnMs8Y3HB49MnMral2L0WVzpL
|
||||
ydhfUNIVb2ZQ7dj1/t0s4Bl7em0ZW/VRJTeMfKRVN/lC2uIsUH3DgOarpkDSEXup
|
||||
QJla4TtSvQ==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQCUx6zAfpMuhi1m
|
||||
BkD1WJdLMEltK19rE8av/PZHZMkt57W9vL1V80HU1OLoc28t8UTjsGGflZ9XDDZl
|
||||
tpQ6Z63cjEuDMAtILzqHCzLCAjziu/9M9KCpLtuRJDI3aw5Awm882szH8yTQ2M+s
|
||||
xxGpnDUgKUqDSAYTfZDtUbl+9sr/uXxPVn2gYxvumOeYyKEla4IxvI8QLQk+QozB
|
||||
7uY16CeVmB33v1dl+fnjU9wq4Q0aHaD3oVr0spfrQgrkrWdz7O7UGmrhMROmm0IE
|
||||
BWQWIYCBTM2BiuYkzxrv6ywJqhzpCpsordFB49YVd5JleuYsObRH4QUMd4Vr2iJa
|
||||
mUnsChjdAgMBAAECggEBAI7PzCdKWIVEDrfsMNZRH4jw5MqB46mo5gNwUgbd267Q
|
||||
yEdEsImcYwilANoYVBRJj9LvMAY7XSP1eRHRXB9j/iPCF4npyCqWCxwtx58q/r61
|
||||
rq5z8vPzIpgDoqBHhvrqqFRFwmP8JM7EDzTOMUoZw3UHrZquvAZhdYgX9nLE+r7U
|
||||
Gqybj1kLlTkTTPkNittCA4su6r4JXbH22ydQ7EdEqS+4mIzodKxW6cuxCscah4kb
|
||||
3D5xkX9eXp0zYvmPTXLiIXTzcDLTlKHoDUM5VFgKcO9677Z5vqIWHudAY8ip93GW
|
||||
EM6gU8wTURvw05V/A0+pD+Cksen42pyz7Myeh2SEjBECgYEAxL/OpyYyhnwIoIla
|
||||
/SJh7YdJQnUt46nglrcRaKOmNHSbFsB7oC/Dy/GEDKhobupW7BP275DsG183NiWH
|
||||
HxW1qPLAmF+Zo4AbwGXoMyUoAfGOY4qYuxNMSqe4UfklZQM7hpxYMl4ww9pGSrPf
|
||||
l2ZTrTypjf/PDWFfk8xYCDDzx58CgYEAwZW5LQHefGS1h2vHJv7d5WoxMABoEv5A
|
||||
Nnon4aVle2/lRyHnbkSaU+THLF+hqN3FevKNbdgID7trLaKz/AQ7+dFxoccZMK1r
|
||||
5SBbomQ+AN+N2CzqweHhFxnThFuiERGnrauIxZBP71neP85PXmeyn9HaAQ66+W0k
|
||||
4YmR1N6B/gMCgYEAgTOoJHHcCh6Xl7y7iLG0d0Q5IrBKs0+SUcbkYr/c3GOamOVM
|
||||
CdR0EpCGc71/3x56eEtgBNA5jHwJiMA6LHqYMdtACI/3F7x//OevBS8oR6Z2J/4S
|
||||
7/7rQbdEPmiLWvs1ct9mt6TNB0BmmpXmhcjHuGK2wa40LQg9uJQfVzm2TOcCgYEA
|
||||
mwOIr8iiXxvJ3PHqHIjUKQP69UQuEp9zzevNibwG4mw8vdQhXUQkDG/TKe4+JlnH
|
||||
6+bUZ5QpCGf8sCNsWq8NU8NqabBjtH36OxTJK+V3XP2muOdm6PA2bWgp3v/9bAum
|
||||
KMSGFiW0TKa6+H79QUxqVd4V4ujnwhmrActGcp3mm/8CgYEApw7jpRIG31ZCVAcr
|
||||
BmeAECVFG8JzV6qrw8DEW44TY/6DcCKRhsFmRYJxMfw46EFYXIAOuF0CaqI7t29A
|
||||
K4HNlFDg0j6rU2mb2F1W+sikfd3Z2Jbmayq6zRDioqFK9K7B8K+NsJSdb/TChtHk
|
||||
EMpZ22XlST/rMKktdpoJlbmHgRE=
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD0fwepds0VJPT6
|
||||
09k3eoQVRdUYSSAznZYVg/h/vqmYJH3VJWo5Ff9VcT5gHEy0GllVoAxLVisHu77Z
|
||||
5n+YBS3hPuR3M0u/nfteWBwXyntXfUS+95gvo9exmemYt7kJeRZCl8yD3hcL/UgP
|
||||
ndiF7PsFWsHhrLePDDZy52VtCV/ge9ScNMhq8sLzkSXAqgTDilAadCC0W1CSzlgb
|
||||
OUVXB1rryaiCwER2g8TFZpplTuPM7wbTWlE9GaPc5xdEX3PwXH6SZq7F2mTY+mw5
|
||||
OOIqi+QSLf97u6/7VR1T5k0OBE8PDjE5SXo7VCIz5gBmsl3sQAgFrMtfFgpr6USF
|
||||
TO1690m9AgMBAAECggEABrt3DfZGEY07Nqs92bPPWRjwvsgIBuEnDbrHeAMGFKOl
|
||||
QwjSSuCdb4WcVVVU0l0VtSXLTjQWSr1OH8i484oUTZW9AOrswh8QRHSHeis6krnn
|
||||
D51t4hqa7kUXRCaDm0HA4xQJebRpl4xW9IvLjMKDVfjTX7Vbt5Nl7hY2Oiv408uf
|
||||
U0qhKAXQ/Ntrw1jGm5gc3V7SdNokXxSlIu6e9gcozi62qG0dggcEvE8JlrrU46EM
|
||||
m9bOUkdU1Zp4LYgKNlVmly+do0ksl3ia0POQUWJh11UosIhPmuJ1Tvu/eBcdO4y3
|
||||
/5iKQGmB7/FCXtl94QXt3LsiyIO5yDwq4Mwfihd4QQKBgQD2Xz9s/ZqFTUFjZiIq
|
||||
7kiPHnM3MMsdaRihCWShtMOfuO9itDvVPxMsFy+bKgaL1jg27/rp+2ee/8/btMtc
|
||||
gGBTwzoTJ1nDl3yMPH8Dqrz57yBxroXTvqzgw/DqUtt8dpZwS6nSj3R59LNtIYOw
|
||||
a1cze8WQtYI5sJ75M7BshVeqwQKBgQD+DQQMEdwriaso5Jpq4XYJE2hjjHyOTPjF
|
||||
0vYlNu388zOe1xKu3kbE6xr7bzD9l47JDCJkZUTdVEIYCU/GSYlXbJA7KumTvyEI
|
||||
kDUkw2Z5ER6M6VWSBBG975+7ZL4S3u6scZuoPuA15vSt8sTRJ+UxjZqNHxWWgNO0
|
||||
vQMCeMLJ/QKBgFQ79oyGHLms00lv1wjElYxRReU9yoRQtXoBoyVij2vhp/8gTkC3
|
||||
ow91EfLEKJ7Q7EFkRW6QZTpIjkG5C7qhrc2VtxprXtZvycaMvIR9cMUnS/lySRE/
|
||||
ZQ4oEAudrqtcRE06oWJ7Z8B2uI38YnEEEjlo/QBf/plI2OGtGYnRAUtBAoGBAJQY
|
||||
ik9u6eYHbtt7x/ieTeykf6nob4OUo0DO5eZzyvA15dWmkqGVubN5SlVgUDLEctwI
|
||||
UtQrpKVRROY2J2bz3zgzdTDIpzkVpfAUAKbZsZbJwAFs1BE2hhEu6vKWm6bshj3I
|
||||
THEbliBV7jSo3MsAcr8cSQgTIsaFeuRVereqJgMRAoGBANZOGAmDceSNJLUxwoMD
|
||||
0wMhc178ghhGAWeN4z+5OqHDCWEnyTC2WIeUQZ9muJCfv6rOTw/wKEP7J5IRECin
|
||||
RJeemh6mw4jTMPJSmfq3tjuy1gFXCzmSlI78ekSfvV8vJDLJJ6h+QFQoXXYAPDOC
|
||||
Y7Mi8PnYxe/pvvhSjL1aI/aD
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
Binary file not shown.
5
crate/cli/test_data/certificates/p12/generate_pkcs12.sh
Executable file
5
crate/cli/test_data/certificates/p12/generate_pkcs12.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#! /bin/bash
|
||||
|
||||
rm output.p12
|
||||
|
||||
openssl pkcs12 -export -inkey cert.key -CAfile subca.pem -passout pass:secret -out output.p12 -in cert.pem -certfile subca.pem
|
Binary file not shown.
|
@ -1,20 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMzCCAhsCCQDTJGaQvJLD0jANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJG
|
||||
UjEMMAoGA1UECAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRl
|
||||
c3QxGjAYBgNVBAMMEUFjbWUgVGVzdCBSb290IENBMB4XDTIzMDUxOTE1Mjk0NloX
|
||||
DTMzMDUxNjE1Mjk0NlowXTELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwG
|
||||
A1UEBwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MR0wGwYDVQQDDBR1c2VyLmNs
|
||||
aWVudEBhY21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALM0
|
||||
r97hLAuvLGxZtvTRR5BTC57SiRXMezsMMnsjatq3o6KWhXw9zBDb6FF2be9ftyO6
|
||||
Mbyo1RGAmHw6o+Sei9p0jImOWIGitibhhYj/8PtyDoHurlKlf5i5/qZ+hRuFVrqv
|
||||
76E9V+fSE22whOgTbHY0L5yYhWGAGn9MUhod7CjE4Q5HHrZCNIu69Dhgv+eB+Xlc
|
||||
arco0sdy975Pv4OujQGBwJp3J5RyvnvMIVf+UKnuA3eK9C9nv4TCocOhluY7oFM/
|
||||
VrmFaMbHDskFM0miJKUvj8Rg2PN8YuA4VtyYUkQFYBBwiGbgX4AZ7gnAAbVVjvbr
|
||||
DIqnFLNRnSvEaKPxhV0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAbrnCV9FmZfeS
|
||||
MiCiOkp4XOzDYZ2ENr8kN7+UNul9ngREXM3aCvK+DsKlvdqySoyFiwX9hkIOK6AL
|
||||
QvPW5veI4kwi1Bh5UnzwPCSrEvrMF41bne9M/GQ2X0V2mZtCfagP3BFcqFliSvVB
|
||||
qXdiujnf1tREYLHFHmefPPhtO21mnh7LJsEtkccFKcbrMAWzrKGuVR5T9XNpfPUZ
|
||||
zB6i24369TKm2Mrmw7yuVTBtdyZDaigckLvDuI61suM+Yd7MtjJE471A2Csjg1MI
|
||||
Zk8AW9ntN/EF5rsbgo2IzxEpfGxZH7vW5AiuLiuJcLsFs4L+WmntVL9FoQ0df80y
|
||||
MZRp6z78Mw==
|
||||
MIIDPjCCAiYCFGna/+9McMd1iqu/lOb1Tr6GhDEcMA0GCSqGSIb3DQEBCwUAMFox
|
||||
CzAJBgNVBAYTAkZSMQwwCgYDVQQIDANJZEYxDjAMBgNVBAcMBVBhcmlzMREwDwYD
|
||||
VQQKDAhBY21lVGVzdDEaMBgGA1UEAwwRQWNtZSBUZXN0IFJvb3QgQ0EwHhcNMjMx
|
||||
MjA2MTMyODUyWhcNMzMxMjAzMTMyODUyWjBdMQswCQYDVQQGEwJGUjEMMAoGA1UE
|
||||
CAwDSWRGMQ4wDAYDVQQHDAVQYXJpczERMA8GA1UECgwIQWNtZVRlc3QxHTAbBgNV
|
||||
BAMMFHVzZXIuY2xpZW50QGFjbWUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAoNrvWrA14HfujCmcvrlDeNnUfKZn/aOpzozUOeTtSKBjmYwMPhSU
|
||||
z6Ykt6DqDiw81vpJpal3GmWkbrHtb1FAjvtBosyxAnluAd8ErcacMkWfGXF0s9wl
|
||||
06bEQKBzBOqmIZ3w1yGWEno+QGISojb+jtPJ+LUgJTwTaGMfcpmgTsnOAHd5pOzD
|
||||
60py/xZr5hJRnO782uraFZ2l7WCiSwd2nmjMZEgAuLvqffjHPCuowcLdSlulgwgN
|
||||
8LGY2B8JUW0xAgIaK3MVW0B5pm1iWr7135gtx+oU9sZ/xsirFDAlhIunhmJ7Gzrh
|
||||
tD9/UX0QpkDRvm7OngC6DIem5JKKSRGCSwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQBuPFfCSx3eMFjd8IExo5Yz1liVueV/Svl8TWkTr5J1hXMsY7xeg4BfRTz6+Sft
|
||||
UQkSfMASy/GTWY6i7g8i4sc+FJd3ph4o4OaRNA2YzEk5sUVsTxwL+0xIb5TtJZaD
|
||||
GyHu4JvZ/lrVAbFmLLJMiHXVA6bYAZADg43Bao3WrKhK6BE5gMQ0ZzwnIn6yqWju
|
||||
abvDe3HX6RsWqxczIf8dsO1TEAnwbcq4034ATpXLzgdzrX3zSWj50kgwcqB2c8jN
|
||||
yK1u8I5Z8YNkfgpeekZNCsqrKzWGqtwyxUpZk11gO6LP1UCgt6E0hpBXxXCDbQRs
|
||||
LXhVsjWXWOBJIHTafzp13tpC
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICojCCAYoCAQAwXTELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA0lkRjEOMAwGA1UE
|
||||
BwwFUGFyaXMxETAPBgNVBAoMCEFjbWVUZXN0MR0wGwYDVQQDDBR1c2VyLmNsaWVu
|
||||
dEBhY21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALM0r97h
|
||||
LAuvLGxZtvTRR5BTC57SiRXMezsMMnsjatq3o6KWhXw9zBDb6FF2be9ftyO6Mbyo
|
||||
1RGAmHw6o+Sei9p0jImOWIGitibhhYj/8PtyDoHurlKlf5i5/qZ+hRuFVrqv76E9
|
||||
V+fSE22whOgTbHY0L5yYhWGAGn9MUhod7CjE4Q5HHrZCNIu69Dhgv+eB+Xlcarco
|
||||
0sdy975Pv4OujQGBwJp3J5RyvnvMIVf+UKnuA3eK9C9nv4TCocOhluY7oFM/VrmF
|
||||
aMbHDskFM0miJKUvj8Rg2PN8YuA4VtyYUkQFYBBwiGbgX4AZ7gnAAbVVjvbrDIqn
|
||||
FLNRnSvEaKPxhV0CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBj8GXhASmFJ0z8
|
||||
S5TR45z/J7omLW8sEsD1XfSHBRpPzZa8+K8tpIVCztP8zuQZqmUv+yf6K9miLyjW
|
||||
OqJgkSOLoj3sZIOfEeKqGzviQosdS2xxhE68U6/Wy8S6BXlfo5rAYsQPAT5tpZJw
|
||||
2OBT7sl4mfYqyG7PN7zM0HuMC18epw3ndrl6KOOS2kg/RPJks4eRf1kOnZHXHAsn
|
||||
g0HoVHEaYRlKVQXhWQmO0mgeJgtNRSPFCs1MXP8kefGvgJCj77WBHewKq3INA9Ck
|
||||
ryVQ5eesI6ByhcXHLN3ZdiBC4dESxEjHWLIJ+XDUa56cZ9OvWjQxybEYYiYYEYOI
|
||||
hf91pd57
|
||||
dEBhY21lLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDa71qw
|
||||
NeB37owpnL65Q3jZ1HymZ/2jqc6M1Dnk7UigY5mMDD4UlM+mJLeg6g4sPNb6SaWp
|
||||
dxplpG6x7W9RQI77QaLMsQJ5bgHfBK3GnDJFnxlxdLPcJdOmxECgcwTqpiGd8Nch
|
||||
lhJ6PkBiEqI2/o7Tyfi1ICU8E2hjH3KZoE7JzgB3eaTsw+tKcv8Wa+YSUZzu/Nrq
|
||||
2hWdpe1goksHdp5ozGRIALi76n34xzwrqMHC3UpbpYMIDfCxmNgfCVFtMQICGitz
|
||||
FVtAeaZtYlq+9d+YLcfqFPbGf8bIqxQwJYSLp4Ziexs64bQ/f1F9EKZA0b5uzp4A
|
||||
ugyHpuSSikkRgksCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAz3Mej3vhOAFPU
|
||||
Jc5H+cYNdPLPahjJDwCzrlhSg8FcgNE9NoP2WZqln1PcYHGVSCr2P19w7pfK9/9r
|
||||
HxbKunNkafG7JYtUtVHqvK1jtoVA3AD7nPMpeqIYudKIICUPnknarYOZcvkf5Iit
|
||||
uRGwKUsPHMR1HVZA1fes38zzAwJWJdnR6X4ws10Q1RLKhDu2ighGPpzIAtOTPSLf
|
||||
uQcrzri/bZw5Hur4pisA1KKGClI9nuSh18dvsW1t15qFCVfCXpSS2Zwy5AOcS+C4
|
||||
Q30ZXftVn4rz0hOAv2Gn3xp5baUGO13JQVq/WUbr+M4MHiW7hSdrSsCWhyBLVKd1
|
||||
9wryWIFq
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzNK/e4SwLryxs
|
||||
Wbb00UeQUwue0okVzHs7DDJ7I2rat6OiloV8PcwQ2+hRdm3vX7cjujG8qNURgJh8
|
||||
OqPknovadIyJjliBorYm4YWI//D7cg6B7q5SpX+Yuf6mfoUbhVa6r++hPVfn0hNt
|
||||
sIToE2x2NC+cmIVhgBp/TFIaHewoxOEORx62QjSLuvQ4YL/ngfl5XGq3KNLHcve+
|
||||
T7+Dro0BgcCadyeUcr57zCFX/lCp7gN3ivQvZ7+EwqHDoZbmO6BTP1a5hWjGxw7J
|
||||
BTNJoiSlL4/EYNjzfGLgOFbcmFJEBWAQcIhm4F+AGe4JwAG1VY726wyKpxSzUZ0r
|
||||
xGij8YVdAgMBAAECggEAcncz4xRG8wuoP2kqsMPAh1JUONVX1MGw8O2AjSD5Ts0/
|
||||
y0mD5/D9GMOuZ+JSpDSqITr8K/pXZn+SZr96EjynLhmF7xMqO1u4J6ujhPeecK3Q
|
||||
0HOpi4bEssQTATwNP5/y3vokAQTS0nNgD49RxX8qp3H7+3V8tOODiU4xnxb/0qWk
|
||||
wzd/CFdED+7UH6PZvx0O5gNpr6vFaQ1WX9mv+DKvlPDW44O2zNsOgoc1tsj0dBPp
|
||||
Ut8AlhLBohnddRpam0nqDZYB5ipv7KV4Qe7C6nfMaZOx13jQ6Zh6r7gONJZgXWUv
|
||||
RT6iCCATBXjItOtupkqd/rxeiu+E3n37JRmzck80AQKBgQDkLHvbJ19gJZK2+dHq
|
||||
tFjb3k2yagHz3EEtZc81f/vs+5srJd8LfFKjeb1BhQkI8s6JXXIdtJH8Cj3Tb7xT
|
||||
AFG2KCxHIkjbw6/b8F5AOr3Jh0i81pwMZqsvK7T7/QrLqpCiDXMSYEXGodc9KQ8j
|
||||
jSR9IdVdyYLFrgq69+/1ueJ/AQKBgQDJD3A3E9Qelz8tlGtd5jqmDcUMcZdXC89U
|
||||
IFMwFkjofmXDJ3yOvmTVyhv8AqR8sxpU1ea+PmTGnE9SnJ85+AAIRY3ZwVI5OTEc
|
||||
SKnB42mn3R6n20DP/ATFplhZ9UcOs2aP/wcgvzeflGSR0BlHrNWyUZTT7CbPpCn9
|
||||
fT2y8wtiXQKBgCc7DsCLcHaTfzo+kb0M7QpAmpNGbreC8yHfE1Vbf/ErAW7VwBe1
|
||||
dG/vCn8tZHRJawFrM6ev2DnBeQfVeke7ElGDbrl8R5KhfqcOGOZqMx9nRzZQn9vx
|
||||
+xTNKvz4cNa7qMp0DYjnTJfuU5eMa7HtHoz1OD4722QpnGaxImzZXPwBAoGAd+ok
|
||||
REUoOwJ75MRjcMJycj0+K9jHqVva0NLiqohv/XH9YXJ4gG4fl76OCDTPQ6xSZQya
|
||||
LRbrZeUuDhhpgtpdspFBNAFv978bgkH4NTJb/okL0pMaybEGa5d1lFmMgsEOx40U
|
||||
BDzngN6xSKHzoeL8JPkxKV/sGeVQQeZjWQpJ3OUCgYAQX1begoozsV7UCabhON8I
|
||||
EX0457fgS64eR8TZIHazEsXQ+sJOIBEWPeFqNlbeUtrdVqvMFw6IBFJ5I9K0P9X1
|
||||
pveKBTkP4NRQvEyAd49hzsKBhkMLFTTbDN9fxA9VU4wP12ARPv5V1NdeHbYQOBSC
|
||||
woxbGNZ9VRIGlsTp0Mty5g==
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCg2u9asDXgd+6M
|
||||
KZy+uUN42dR8pmf9o6nOjNQ55O1IoGOZjAw+FJTPpiS3oOoOLDzW+kmlqXcaZaRu
|
||||
se1vUUCO+0GizLECeW4B3wStxpwyRZ8ZcXSz3CXTpsRAoHME6qYhnfDXIZYSej5A
|
||||
YhKiNv6O08n4tSAlPBNoYx9ymaBOyc4Ad3mk7MPrSnL/FmvmElGc7vza6toVnaXt
|
||||
YKJLB3aeaMxkSAC4u+p9+Mc8K6jBwt1KW6WDCA3wsZjYHwlRbTECAhorcxVbQHmm
|
||||
bWJavvXfmC3H6hT2xn/GyKsUMCWEi6eGYnsbOuG0P39RfRCmQNG+bs6eALoMh6bk
|
||||
kopJEYJLAgMBAAECggEAAlgOYtjsgA/fVwWINjNG62zpLsPSAh0vbUYaFZnjZ0qH
|
||||
CQbEaucr3/bA1DgxEPHOFSfiiNp2VNkkU0SefB/H/A1nQHMRJUMVuktAqzOYtRbU
|
||||
oa9IjxJnLrVgaLyt0GWG9Dhz+P6RTEWhwJhtQxXgEb6+U7R3+nLsqXnATJA2iM9c
|
||||
FmGuBJnUe6ej5DZVCk1TOmoOa12MUpRYmO45A8IdhbTKfj+3IVXhKvIVFMwfZONj
|
||||
T/uPmplE7ElR/YlVBGeiKhQuuhWNnf0qwfooaAu1tbZU9jXUzDuK4ITZG7HD14ov
|
||||
qn494MC234ETu8yzhlhqmpF5iu6f335ev815Hu8EgQKBgQDZqtxY5Ktys5GkDD+Z
|
||||
6HvES1DpipBODlRZrr4jOvCJGvfmsW1LYQUMbt8VfYe3xJ6juC+6p2+XeyACNbow
|
||||
W8My4/jhYwyzOOKaIPKhHHxj6VX/+6/q/mkuF0E9OGyRzULsRmfcs4R42XhkiK5d
|
||||
OELWxRaN1OB0viPjg3N6t1ATwQKBgQC9LsycyfI3Wol7nuAigenHBa3vjGiR5EJH
|
||||
4apI61SBzM5l0m4Kkq9+rOwdzmbFj0tO6qqNzBT4214L0PNO+lCTPMUvmOCzNkLd
|
||||
39bdmnFHU80fcfINidTYgTpTtgBIk5/L9K2V1B6ErK8u7BM87vIzANRWHyEgjMh9
|
||||
XmGPmCbpCwKBgQCmDETZ/1+XOctR1RIzy/mWzknkTxM0qJPKcpaT86OJRCx3LUUO
|
||||
Ku4aBP5ju4ZsNy86AAlRH+fuLDxH00q9F1N6oBS9g70tf6jGIXpWU4/E/Dzh8dPK
|
||||
tdfxFEZteHzCYU67Rh53a+8T7fp83xP9Ay1h/6nr+shb5q0kI6RVqkAJQQKBgQCb
|
||||
mXVjc9oL2yR/D+KLn0y3jB1OjK6paBN36czUIvKju9768oPdoF5Fk1a1AUGYNk6b
|
||||
fvl+nR+Wu17z2w1zpQBGydHpXxVZcUS4FtYz+EY5g1yQA3kx127AEDH4DhbXmsvw
|
||||
xbNMK2Zae2mu7y63jFSazJDYsMvfaMuyCcG2iE9glwKBgCLw6YsWiZngpESy57e/
|
||||
upHXQMd2Hc9k7f2fR1cSuZ5m0NS9dbMxCdX53c22DhPj261Ej8PbIKM8gUAs3X/U
|
||||
ABZ63xJfGC0vGaO8PKHnDYSa0Br8Guq+G3K/1fFv8ujkX8gcBnt3w3A3iIFsw8GC
|
||||
9XWiwNeQej22P7nnLl5GjHqz
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
Binary file not shown.
|
@ -11,16 +11,11 @@ cosmian_kmip = { path = "../kmip" }
|
|||
cosmian_kms_utils = { path = "../utils" }
|
||||
http = { workspace = true }
|
||||
josekit = { workspace = true }
|
||||
openssl = { workspace = true }
|
||||
ratls = { workspace = true }
|
||||
log = "0.4"
|
||||
reqwest = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tee_attestation = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-util = { workspace = true }
|
||||
url = { workspace = true }
|
||||
webpki-roots = { workspace = true }
|
||||
log = { version = "0.4.20", features = [] }
|
||||
|
|
|
@ -1,335 +0,0 @@
|
|||
use std::{
|
||||
io::{BufReader, Read},
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
// re-export the kmip module as kmip
|
||||
use cosmian_kms_utils::access::SuccessResponse;
|
||||
use http::{HeaderMap, HeaderValue, StatusCode};
|
||||
use openssl::x509::X509;
|
||||
use ratls::verify::{get_server_certificate, verify_ratls};
|
||||
use reqwest::{
|
||||
multipart::{Form, Part},
|
||||
Body, Certificate, Client, ClientBuilder, Identity, Response,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tee_attestation::TeeMeasurement;
|
||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||
use url::Url;
|
||||
|
||||
use crate::error::RestClientError;
|
||||
|
||||
/// A struct implementing some of the 50+ operations a KMIP client should implement:
|
||||
/// <https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=kmip>
|
||||
#[derive(Clone)]
|
||||
pub struct BootstrapRestClient {
|
||||
server_url: String,
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl BootstrapRestClient {
|
||||
/// Upload a PKCS12 file containing the KMS server's SSL certificate and private key.
|
||||
/// The KMS server will be started in HTTPS mode.
|
||||
///
|
||||
/// Call the `pkcs12_password()` method to supply the PKCS12 password
|
||||
/// if it is a non-empty string,
|
||||
pub async fn upload_pkcs12(
|
||||
&self,
|
||||
pkcs12_file: &PathBuf,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
self.upload("/pkcs12", pkcs12_file).await
|
||||
}
|
||||
|
||||
pub async fn set_pkcs12_password(
|
||||
&self,
|
||||
pkcs12_password: &str,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct PasswordConfig {
|
||||
pub password: String,
|
||||
}
|
||||
self.post(
|
||||
"/pkcs12-password",
|
||||
Some(&PasswordConfig {
|
||||
password: pkcs12_password.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_redis_findex_config(
|
||||
&self,
|
||||
database_url: &str,
|
||||
master_password: &str,
|
||||
findex_label: &str,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct RedisFindexConfig {
|
||||
pub url: String,
|
||||
pub master_password: String,
|
||||
pub findex_label: String,
|
||||
}
|
||||
self.post(
|
||||
"/redis-findex",
|
||||
Some(&RedisFindexConfig {
|
||||
url: database_url.to_string(),
|
||||
master_password: master_password.to_string(),
|
||||
findex_label: findex_label.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_postgresql_config(
|
||||
&self,
|
||||
database_url: &str,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct UrlConfig {
|
||||
pub url: String,
|
||||
}
|
||||
self.post(
|
||||
"/postgresql",
|
||||
Some(&UrlConfig {
|
||||
url: database_url.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_mysql_config(
|
||||
&self,
|
||||
database_url: &str,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct UrlConfig {
|
||||
pub url: String,
|
||||
}
|
||||
self.post(
|
||||
"/mysql",
|
||||
Some(&UrlConfig {
|
||||
url: database_url.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_sqlite_config(
|
||||
&self,
|
||||
path: &PathBuf,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct PathConfig {
|
||||
pub path: String,
|
||||
}
|
||||
self.post(
|
||||
"/sqlite",
|
||||
Some(&PathConfig {
|
||||
path: path
|
||||
.to_str()
|
||||
.ok_or_else(|| {
|
||||
RestClientError::Default(format!("Invalid sqlite path: {path:?}"))
|
||||
})?
|
||||
.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_sqlite_enc_config(
|
||||
&self,
|
||||
path: &PathBuf,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct PathConfig {
|
||||
pub path: String,
|
||||
}
|
||||
self.post(
|
||||
"/sqlite-enc",
|
||||
Some(&PathConfig {
|
||||
path: path
|
||||
.to_str()
|
||||
.ok_or_else(|| {
|
||||
RestClientError::Default(format!("Invalid sqlite-enc path: {path:?}"))
|
||||
})?
|
||||
.to_string(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn start_kms_server(
|
||||
&self,
|
||||
clear_database: bool,
|
||||
) -> Result<SuccessResponse, RestClientError> {
|
||||
#[derive(Serialize)]
|
||||
pub struct StartKmsServer {
|
||||
pub clear_database: bool,
|
||||
}
|
||||
self.post("/start", Some(&StartKmsServer { clear_database }))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl BootstrapRestClient {
|
||||
/// Instantiate a new KMIP REST Client
|
||||
#[allow(dead_code)]
|
||||
pub fn instantiate(
|
||||
bootstrap_server_url: &str,
|
||||
bearer_token: Option<&str>,
|
||||
ssl_client_pkcs12_path: Option<&str>,
|
||||
ssl_client_pkcs12_password: Option<&str>,
|
||||
measurement: TeeMeasurement,
|
||||
) -> Result<Self, RestClientError> {
|
||||
let server_url = match bootstrap_server_url.strip_suffix('/') {
|
||||
Some(s) => s.to_string(),
|
||||
None => bootstrap_server_url.to_string(),
|
||||
};
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
if let Some(bearer_token) = bearer_token {
|
||||
headers.insert(
|
||||
"Authorization",
|
||||
HeaderValue::from_str(format!("Bearer {bearer_token}").as_str())?,
|
||||
);
|
||||
}
|
||||
headers.insert("Connection", HeaderValue::from_static("keep-alive"));
|
||||
|
||||
let builder = ClientBuilder::new();
|
||||
|
||||
// If a PKCS12 file is provided, use it to build the client
|
||||
let builder = match ssl_client_pkcs12_path {
|
||||
Some(ssl_client_pkcs12) => {
|
||||
let mut pkcs12 = BufReader::new(std::fs::File::open(ssl_client_pkcs12)?);
|
||||
let mut pkcs12_bytes = vec![];
|
||||
pkcs12.read_to_end(&mut pkcs12_bytes)?;
|
||||
let pkcs12 = Identity::from_pkcs12_der(
|
||||
&pkcs12_bytes,
|
||||
ssl_client_pkcs12_password.unwrap_or(""),
|
||||
)?;
|
||||
builder.identity(pkcs12)
|
||||
}
|
||||
None => builder,
|
||||
};
|
||||
|
||||
// Get and verify the ratls certificate in order to use it as the only valid root CA
|
||||
let bootstrap_server_url = Url::parse(bootstrap_server_url)?;
|
||||
|
||||
let ratls_cert = get_server_certificate(
|
||||
bootstrap_server_url
|
||||
.host_str()
|
||||
.ok_or(RestClientError::Default(
|
||||
"Missing 'hostname' in bootstrap server url".to_string(),
|
||||
))?,
|
||||
u32::from(bootstrap_server_url.port().unwrap_or(443)),
|
||||
)
|
||||
.map_err(|e| RestClientError::RatlsError(format!("Can't get RATLS certificate: {e}")))?;
|
||||
|
||||
let ratls_cert = X509::from_der(&ratls_cert)
|
||||
.map_err(|e| {
|
||||
RestClientError::RatlsError(format!("Can't convert certificate to DER: {e}"))
|
||||
})?
|
||||
.to_pem()
|
||||
.map_err(|e| {
|
||||
RestClientError::RatlsError(format!("Can't convert certificate to PEM: {e}"))
|
||||
})?;
|
||||
|
||||
verify_ratls(&ratls_cert, measurement)
|
||||
.map_err(|e| RestClientError::RatlsError(e.to_string()))?;
|
||||
|
||||
let ratls_cert = Certificate::from_pem(&ratls_cert)?;
|
||||
|
||||
// Build the client
|
||||
Ok(Self {
|
||||
client: builder
|
||||
.danger_accept_invalid_certs(true)
|
||||
.tls_built_in_root_certs(false) // Disallow all root certs from the system
|
||||
.add_root_certificate(ratls_cert) // Allow our ratls cert
|
||||
.connect_timeout(Duration::from_secs(5))
|
||||
.tcp_keepalive(Duration::from_secs(30))
|
||||
.default_headers(headers)
|
||||
.build()?,
|
||||
server_url,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn post<O, R>(&self, endpoint: &str, data: Option<&O>) -> Result<R, RestClientError>
|
||||
where
|
||||
O: Serialize,
|
||||
R: serde::de::DeserializeOwned + Sized + 'static,
|
||||
{
|
||||
let server_url = format!("{}{endpoint}", self.server_url);
|
||||
let response = match data {
|
||||
Some(d) => self.client.post(server_url).json(d).send().await?,
|
||||
None => self.client.post(server_url).send().await?,
|
||||
};
|
||||
|
||||
let status_code = response.status();
|
||||
if status_code.is_success() {
|
||||
return Ok(response.json::<R>().await?)
|
||||
}
|
||||
|
||||
// process error
|
||||
let p = handle_error(response).await?;
|
||||
Err(RestClientError::RequestFailed(p))
|
||||
}
|
||||
|
||||
pub async fn upload<R>(&self, endpoint: &str, file: &PathBuf) -> Result<R, RestClientError>
|
||||
where
|
||||
R: serde::de::DeserializeOwned + Sized + 'static,
|
||||
{
|
||||
let server_url = format!("{}{endpoint}", self.server_url);
|
||||
|
||||
// open the file async
|
||||
let file = tokio::fs::File::open(file).await?;
|
||||
|
||||
// create a body wrapping the async file stream
|
||||
let stream = FramedRead::new(file, BytesCodec::new());
|
||||
let file_body = Body::wrap_stream(stream);
|
||||
|
||||
//make a form part of the file
|
||||
let file_part = Part::stream(file_body)
|
||||
.file_name("bootstrap.p12")
|
||||
.mime_str("application/octet-stream")?;
|
||||
|
||||
//create the multipart form
|
||||
let form = Form::new().part("file", file_part);
|
||||
|
||||
//send request
|
||||
let response = self.client.post(server_url).multipart(form).send().await?;
|
||||
|
||||
// check the status code response
|
||||
let status_code = response.status();
|
||||
if status_code.is_success() {
|
||||
return Ok(response.json::<R>().await?)
|
||||
}
|
||||
|
||||
// process error
|
||||
let p = handle_error(response).await?;
|
||||
Err(RestClientError::RequestFailed(p))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct ErrorPayload {
|
||||
pub error: String,
|
||||
pub messages: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Some errors are returned by the Middleware without going through our own error manager.
|
||||
/// In that case, we make the error clearer here for the client.
|
||||
async fn handle_error(response: Response) -> Result<String, RestClientError> {
|
||||
let status = response.status();
|
||||
let text = response.text().await?;
|
||||
|
||||
if !text.is_empty() {
|
||||
Ok(text)
|
||||
} else {
|
||||
Ok(match status {
|
||||
StatusCode::NOT_FOUND => "Bootstrap server endpoint does not exist".to_string(),
|
||||
StatusCode::UNAUTHORIZED => "Bad authorization token".to_string(),
|
||||
_ => format!("{status} {text}"),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
use base64::{engine::general_purpose::STANDARD as b64, Engine as _};
|
||||
// re-export the kmip module as kmip
|
||||
use cosmian_kmip::kmip::{
|
||||
kmip_operations::{
|
||||
|
@ -17,12 +16,8 @@ use cosmian_kmip::kmip::{
|
|||
},
|
||||
ttlv::{deserializer::from_ttlv, serializer::to_ttlv, TTLV},
|
||||
};
|
||||
use cosmian_kms_utils::{
|
||||
access::{
|
||||
Access, AccessRightsObtainedResponse, ObjectOwnedResponse, SuccessResponse,
|
||||
UserAccessResponse,
|
||||
},
|
||||
tee::QuoteParams,
|
||||
use cosmian_kms_utils::access::{
|
||||
Access, AccessRightsObtainedResponse, ObjectOwnedResponse, SuccessResponse, UserAccessResponse,
|
||||
};
|
||||
use http::{HeaderMap, HeaderValue, StatusCode};
|
||||
use josekit::{
|
||||
|
@ -428,29 +423,6 @@ impl KmsRestClient {
|
|||
self.get_no_ttlv("/access/obtained", None::<&()>).await
|
||||
}
|
||||
|
||||
/// This operation requests the server to get the sgx quote or sev attestation report.
|
||||
pub async fn get_attestation_report(
|
||||
&self,
|
||||
nonce: &[u8; 32],
|
||||
) -> Result<Vec<u8>, RestClientError> {
|
||||
let quote: String = self
|
||||
.get_no_ttlv(
|
||||
"/tee/attestation_report",
|
||||
Some(&QuoteParams {
|
||||
nonce: b64.encode(nonce),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(b64.decode(quote.as_bytes())?)
|
||||
}
|
||||
|
||||
/// This operation requests the server to get the HTTPS certificate.
|
||||
pub async fn get_sgx_enclave_public_key(&self) -> Result<String, RestClientError> {
|
||||
self.get_no_ttlv("/tee/sgx_enclave_public_key", None::<&()>)
|
||||
.await
|
||||
}
|
||||
|
||||
/// This operation requests the version of the server
|
||||
pub async fn version(&self) -> Result<String, RestClientError> {
|
||||
self.get_no_ttlv("/version", None::<&()>).await
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
//required to detect generic type in Serializer
|
||||
#![feature(min_specialization)]
|
||||
|
||||
mod bootstrap_rest_client;
|
||||
mod certificate_verifier;
|
||||
mod error;
|
||||
mod kms_rest_client;
|
||||
mod result;
|
||||
|
||||
pub use bootstrap_rest_client::BootstrapRestClient;
|
||||
pub use cosmian_kmip::kmip;
|
||||
pub use error::RestClientError;
|
||||
pub use kms_rest_client::KmsRestClient;
|
||||
|
|
|
@ -10,6 +10,7 @@ openssl = ["dep:openssl"]
|
|||
pyo3 = ["dep:pyo3"]
|
||||
|
||||
[dependencies]
|
||||
base58 = "0.2"
|
||||
bitflags = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
cloudproof = { workspace = true }
|
||||
|
@ -19,12 +20,13 @@ openssl = { workspace = true, optional = true }
|
|||
pyo3 = { version = "0.20", optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sha3 = { version = "0.10", optional = true }
|
||||
strum = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true, features = ["formatting", "parsing", "serde"] }
|
||||
tracing = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
uuid = { version = "1.6.1", features = ["v4"] }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
cosmian_logger = { path = "../logger" }
|
||||
|
|
27
crate/kmip/src/id.rs
Normal file
27
crate/kmip/src/id.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use base58::ToBase58;
|
||||
#[cfg(feature = "openssl")]
|
||||
use openssl::hash::{hash, MessageDigest};
|
||||
#[cfg(not(feature = "openssl"))]
|
||||
use sha3::Digest;
|
||||
|
||||
use crate::error::KmipError;
|
||||
|
||||
/// Generate a unique ID from a byte slice.
|
||||
///
|
||||
/// Uses SHA3-256 hash function and base58 encoding
|
||||
/// which generates file system friendly IDs.
|
||||
/// # Arguments
|
||||
/// * `bytes` - A byte slice
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use cosmian_kmip::id;
|
||||
/// let id = id(b"Hello World!").unwrap();
|
||||
/// assert_eq!(id, "F4RrBrbeAHQhQQCdoBNUJwSyk3iRr4eRsdULicFwer3p");
|
||||
/// ```
|
||||
pub fn id(bytes: &[u8]) -> Result<String, KmipError> {
|
||||
#[cfg(feature = "openssl")]
|
||||
let digest = hash(MessageDigest::sha3_256(), bytes)?.to_vec();
|
||||
#[cfg(not(feature = "openssl"))]
|
||||
let digest = sha3::Sha3_256::digest(bytes).to_vec();
|
||||
Ok(digest.to_base58())
|
||||
}
|
|
@ -15,6 +15,7 @@ use crate::{
|
|||
WrappingMethod,
|
||||
},
|
||||
},
|
||||
openssl::pad_be_bytes,
|
||||
};
|
||||
|
||||
/// A Key Block object is a structure used to encapsulate all of the information
|
||||
|
@ -57,7 +58,24 @@ impl KeyBlock {
|
|||
match &self.key_value.key_material {
|
||||
KeyMaterial::ByteString(v) => Ok(Zeroizing::new(v.clone())),
|
||||
KeyMaterial::TransparentSymmetricKey { key } => Ok(Zeroizing::new(key.clone())),
|
||||
KeyMaterial::TransparentECPrivateKey { d, .. } => Ok(Zeroizing::new(d.to_bytes_be())),
|
||||
KeyMaterial::TransparentECPrivateKey {
|
||||
d,
|
||||
recommended_curve,
|
||||
} => {
|
||||
let mut d_vec = d.to_bytes_be();
|
||||
let privkey_size = match recommended_curve {
|
||||
RecommendedCurve::P192 => 24,
|
||||
RecommendedCurve::P224 => 28,
|
||||
RecommendedCurve::P256 => 32,
|
||||
RecommendedCurve::P384 => 48,
|
||||
RecommendedCurve::P521 => 66,
|
||||
RecommendedCurve::CURVE25519 | RecommendedCurve::CURVEED25519 => 32,
|
||||
RecommendedCurve::CURVE448 | RecommendedCurve::CURVEED448 => 56,
|
||||
_ => d_vec.len(),
|
||||
};
|
||||
pad_be_bytes(&mut d_vec, privkey_size);
|
||||
Ok(Zeroizing::new(d_vec))
|
||||
}
|
||||
KeyMaterial::TransparentECPublicKey { q_string, .. } => {
|
||||
Ok(Zeroizing::new(q_string.clone()))
|
||||
}
|
||||
|
|
|
@ -459,12 +459,23 @@ impl<'de> Deserialize<'de> for TTLV {
|
|||
/// doesn't provide such conversion.
|
||||
#[must_use]
|
||||
pub fn to_u32_digits(big_int: &BigUint) -> Vec<u32> {
|
||||
// Since the KMS works with big-endian representation of bytearrays, casting
|
||||
// a group of 4 bytes in big-endian u32 representation needs revert iter so
|
||||
// that if you have a chunk [0, 12, 143, 239] you will do
|
||||
// B = 239 + 143*2^8 + 12*2^16 + 0*2^24 which is the correct way to do. On
|
||||
// top of that, if the number of bytes in `big_int` is not a multiple of 4,
|
||||
// it will behave as if there were leading null bytes which is technically
|
||||
// the case.
|
||||
// In this case, using this to convert a BigUint to a Vec<u32> will not lose
|
||||
// leading null bytes information which might be the case when an EC private
|
||||
// key is legally generated with leading null bytes.
|
||||
big_int
|
||||
.to_bytes_be()
|
||||
.chunks(4)
|
||||
.map(|group_of_4_bytes| {
|
||||
group_of_4_bytes
|
||||
.iter()
|
||||
.rev()
|
||||
.fold(0, |acc, byte| (acc << 8) + u32::from(*byte))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#![feature(slice_take)]
|
||||
|
||||
pub mod error;
|
||||
mod id;
|
||||
pub use id::id;
|
||||
pub mod kmip;
|
||||
pub mod result;
|
||||
|
||||
|
|
|
@ -3,5 +3,5 @@ mod private_key;
|
|||
mod public_key;
|
||||
|
||||
pub use certificate::{kmip_certificate_to_openssl, openssl_certificate_to_kmip};
|
||||
pub use private_key::{kmip_private_key_to_openssl, openssl_private_key_to_kmip};
|
||||
pub use private_key::{kmip_private_key_to_openssl, openssl_private_key_to_kmip, pad_be_bytes};
|
||||
pub use public_key::{kmip_public_key_to_openssl, openssl_public_key_to_kmip};
|
||||
|
|
|
@ -21,6 +21,12 @@ use crate::{
|
|||
result::KmipResultHelper,
|
||||
};
|
||||
|
||||
pub fn pad_be_bytes(bytes: &mut Vec<u8>, size: usize) {
|
||||
while bytes.len() != size {
|
||||
bytes.insert(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a KMIP Private key to openssl `PKey<Private>`
|
||||
///
|
||||
/// The supported `KeyFormatType` are:
|
||||
|
@ -131,13 +137,22 @@ pub fn kmip_private_key_to_openssl(private_key: &Object) -> Result<PKey<Private>
|
|||
recommended_curve,
|
||||
} => match recommended_curve {
|
||||
RecommendedCurve::CURVE25519 => {
|
||||
PKey::private_key_from_raw_bytes(&d.to_bytes_be(), Id::X25519)?
|
||||
let mut privkey_vec = d.to_bytes_be();
|
||||
// 32 is privkey size on x25519.
|
||||
pad_be_bytes(&mut privkey_vec, 32);
|
||||
PKey::private_key_from_raw_bytes(&privkey_vec, Id::X25519)?
|
||||
}
|
||||
RecommendedCurve::CURVE448 => {
|
||||
PKey::private_key_from_raw_bytes(&d.to_bytes_be(), Id::X448)?
|
||||
let mut privkey_vec = d.to_bytes_be();
|
||||
// 56 is privkey size on x448.
|
||||
pad_be_bytes(&mut privkey_vec, 56);
|
||||
PKey::private_key_from_raw_bytes(&privkey_vec, Id::X448)?
|
||||
}
|
||||
RecommendedCurve::CURVEED25519 => {
|
||||
PKey::private_key_from_raw_bytes(&d.to_bytes_be(), Id::ED25519)?
|
||||
let mut privkey_vec = d.to_bytes_be();
|
||||
// 32 is privkey size on ed25519.
|
||||
pad_be_bytes(&mut privkey_vec, 32);
|
||||
PKey::private_key_from_raw_bytes(&privkey_vec, Id::ED25519)?
|
||||
}
|
||||
other => ec_private_key_from_scalar(d, other)?,
|
||||
},
|
||||
|
@ -160,16 +175,20 @@ fn ec_private_key_from_scalar(
|
|||
scalar: &BigUint,
|
||||
curve: &RecommendedCurve,
|
||||
) -> Result<PKey<Private>, KmipError> {
|
||||
let nid = match curve {
|
||||
RecommendedCurve::P256 => Nid::X9_62_PRIME256V1,
|
||||
RecommendedCurve::P192 => Nid::X9_62_PRIME192V1,
|
||||
RecommendedCurve::P224 => Nid::SECP224R1,
|
||||
RecommendedCurve::P384 => Nid::SECP384R1,
|
||||
RecommendedCurve::P521 => Nid::SECP521R1,
|
||||
let (nid, privkey_size) = match curve {
|
||||
RecommendedCurve::P256 => (Nid::X9_62_PRIME256V1, 32),
|
||||
RecommendedCurve::P192 => (Nid::X9_62_PRIME192V1, 24),
|
||||
RecommendedCurve::P224 => (Nid::SECP224R1, 28),
|
||||
RecommendedCurve::P384 => (Nid::SECP384R1, 48),
|
||||
RecommendedCurve::P521 => (Nid::SECP521R1, 66),
|
||||
x => kmip_bail!("Unsupported curve: {:?} in this KMIP implementation", x),
|
||||
};
|
||||
let big_num_context = BigNumContext::new()?;
|
||||
|
||||
let mut scalar_vec = scalar.to_bytes_be();
|
||||
pad_be_bytes(&mut scalar_vec, privkey_size);
|
||||
let scalar = BigNum::from_slice(scalar.to_bytes_be().as_slice())?;
|
||||
|
||||
let ec_group = EcGroup::from_curve_name(nid)?;
|
||||
let mut ec_public_key = EcPoint::new(&ec_group)?;
|
||||
ec_public_key.mul_generator(&ec_group, &scalar, &big_num_context)?;
|
||||
|
@ -405,7 +424,7 @@ pub fn openssl_private_key_to_kmip(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use num_bigint_dig::BigUint;
|
||||
use openssl::{
|
||||
bn::BigNum,
|
||||
ec::{EcGroup, EcKey},
|
||||
|
@ -419,7 +438,10 @@ mod tests {
|
|||
kmip_objects::Object,
|
||||
kmip_types::{KeyFormatType, RecommendedCurve},
|
||||
},
|
||||
openssl::{kmip_private_key_to_openssl, private_key::openssl_private_key_to_kmip},
|
||||
openssl::{
|
||||
kmip_private_key_to_openssl,
|
||||
private_key::{openssl_private_key_to_kmip, pad_be_bytes},
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -638,10 +660,14 @@ mod tests {
|
|||
_ => panic!("Invalid key block"),
|
||||
};
|
||||
assert_eq!(recommended_curve, RecommendedCurve::P256);
|
||||
|
||||
let mut privkey_vec = d.to_bytes_be();
|
||||
// 32 is privkey size on P-256.
|
||||
pad_be_bytes(&mut privkey_vec, 32);
|
||||
let private_key_ = PKey::from_ec_key(
|
||||
EcKey::from_private_components(
|
||||
&ec_group,
|
||||
&BigNum::from_slice(d.to_bytes_be().as_slice()).unwrap(),
|
||||
&BigNum::from_slice(privkey_vec.as_slice()).unwrap(),
|
||||
&ec_public_key,
|
||||
)
|
||||
.unwrap(),
|
||||
|
@ -712,11 +738,27 @@ mod tests {
|
|||
_ => panic!("Invalid key block"),
|
||||
};
|
||||
assert_eq!(recommended_curve, RecommendedCurve::CURVE25519);
|
||||
let private_key_ = PKey::private_key_from_raw_bytes(&d.to_bytes_be(), Id::X25519).unwrap();
|
||||
|
||||
let mut privkey_vec = d.to_bytes_be();
|
||||
// 32 is privkey size on X25519.
|
||||
pad_be_bytes(&mut privkey_vec, 32);
|
||||
let private_key_ = PKey::private_key_from_raw_bytes(&privkey_vec, Id::X25519).unwrap();
|
||||
assert_eq!(private_key_.id(), Id::X25519);
|
||||
assert_eq!(private_key_.bits(), 253);
|
||||
let private_key_ = kmip_private_key_to_openssl(&object_).unwrap();
|
||||
assert_eq!(private_key_.id(), Id::X25519);
|
||||
assert_eq!(private_key_.bits(), 253);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conversion_privkey_null_first_byte() {
|
||||
let key = [
|
||||
0, 113, 8, 182, 184, 86, 82, 102, 195, 88, 8, 230, 119, 254, 2, 177, 228, 135, 20, 247,
|
||||
106, 133, 91, 78, 125, 44, 57, 70, 202, 154, 25, 243,
|
||||
];
|
||||
let a = BigUint::from_bytes_be(&key);
|
||||
let mut key_vec = a.to_bytes_be();
|
||||
pad_be_bytes(&mut key_vec, 32);
|
||||
assert_eq!(key_vec, key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,19 +13,18 @@ insecure = []
|
|||
timeout = []
|
||||
|
||||
# Enable all the feature even insecure but timeout
|
||||
# To run in a test environment using a real domain name and enclaves without the rest api limit of let's encrypt
|
||||
staging = ["insecure"]
|
||||
|
||||
# Enable FIPS module feature build. KMS builds in FIPS mode when this is enabled.
|
||||
fips = ["cosmian_kms_utils/fips"]
|
||||
|
||||
# No features (insecure, timeout or staging) and contain non FIPS approved libraries (e.g. Rust Crypto)
|
||||
default = []
|
||||
prod = []
|
||||
|
||||
[dependencies]
|
||||
acme-lib = { git = "https://github.com/Cosmian/acme-lib", branch = "master" }
|
||||
actix-cors = "0.6"
|
||||
actix-files = "0.6"
|
||||
actix-identity = "0.6"
|
||||
actix-multipart = "0.6"
|
||||
actix-rt = { workspace = true }
|
||||
actix-service = "2.0"
|
||||
actix-tls = "3.1"
|
||||
|
@ -49,7 +48,6 @@ josekit = { workspace = true }
|
|||
lazy_static = "1.4"
|
||||
mime = "0.3"
|
||||
openssl = { workspace = true }
|
||||
ratls = { workspace = true }
|
||||
rawsql = "0.1"
|
||||
redis = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
|
@ -62,7 +60,6 @@ sqlx = { version = "0.7.3", default-features = false, features = [
|
|||
"postgres",
|
||||
"sqlite",
|
||||
] }
|
||||
tee_attestation = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true, features = ["local-offset", "formatting"] }
|
||||
# this version of tokio should be the same as the one used in actix-web
|
||||
|
|
|
@ -6,10 +6,7 @@ The KMS server provides several features which can be enabled at compilation tim
|
|||
|
||||
| Feature | Description | Staging | Prod 🔥 |
|
||||
|----------|-------------------------------------------------------------------------------------------------------------------|---------|---------|
|
||||
| auth | Enable authentication. If disabled, multi-user is not supported | ✅ | ✅ |
|
||||
| enclave | Enable the ability to run inside an enclave | ✅ | ✅ |
|
||||
| https | Enable https in the KMS in order to encrypt query between client and the KMS. If disabled, it uses http | ✅ | ✅ |
|
||||
| insecure | Do not verify auth0 token expiration date and https ssl is self-signed (to avoid to be banned by letsencrypt) | ✅ | |
|
||||
| insecure | Do not verify auth0 token expiration date | ✅ | |
|
||||
| timeout | The binary will stop (and won't be able to start again) after a period of time, starting from date of compilation | | |
|
||||
|
||||
**Caption**:
|
||||
|
@ -32,8 +29,6 @@ cargo build --no-default-features
|
|||
For staging environment, you can use `--features=staging --no-default-features`. It will tell the server:
|
||||
|
||||
- to not verify the expiration of OAuth2 tokens if `KMS_JWT_ISSUER_URI` is set.
|
||||
- to use HTTPS connection with unsecure SSL certificates (it will play anyway all the process to get a valid certificates and starts a HTTPS server)
|
||||
- to be runnable only inside an enclave
|
||||
|
||||
### Timeout feature
|
||||
|
||||
|
@ -64,20 +59,16 @@ cosmian_kms_server -h
|
|||
A server for development can be quickly run as follow (with sqlite):
|
||||
|
||||
```sh
|
||||
cargo run --no-default-features -- --public-path /tmp --shared-path /tmp --private-path /tmp
|
||||
cargo run --no-default-features -- --tmp-path /tmp
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```sh
|
||||
export KMS_ENCLAVE_DIR_PATH=/tmp
|
||||
export KMS_CERTBOT_SSL_PATH=/tmp
|
||||
export KMS_SQLITE_PATH=/tmp
|
||||
cargo run --no-default-features
|
||||
```
|
||||
|
||||
The 3 parameters `public-path`, `shared-path` and `private-path` are related to certificate generation in the Secure Enclave. Outside of the enclave, the value of these parameters can be set to `/tmp`.
|
||||
|
||||
## Configure the authentication
|
||||
|
||||
The KMS server relies on an OAuth2 authentication provided by Auth0 to authenticate the user.
|
||||
|
@ -131,86 +122,6 @@ cargo install cargo-make
|
|||
cargo make rust-tests
|
||||
```
|
||||
|
||||
## Production / Running inside a Secure Enclave
|
||||
|
||||
> You can run the KMS on a non-sgx environment for production. In that case, the server will have the same behavior with a lower security level and with some routes disabled for the user.
|
||||
|
||||
At _Cosmian_, for production, the architecture and the security rely on secure enclaves. With no feature flag specified during the building process, the generated binary targets the production environment.
|
||||
|
||||

|
||||
|
||||
To set up the SGX enclave to run the KMS server, please refer to the dedicated [Readme](../../sgx/README.md)
|
||||
|
||||
**Mandatory**: all KMS source codes are fully open source.
|
||||
|
||||
### HTTPS
|
||||
|
||||
The REST API server of the KMS server is launched into a secure enclave. It accepts HTTPS connection only.
|
||||
To be sure that _Cosmian_ can't decrypt the HTTPS flow (in a MITM scenario), the SSL certificate is generated inside the enclave. The private key is not exposed to the host in plain-text.
|
||||
|
||||
**How it works?**
|
||||
|
||||
The KMS will ask a certificate to _Let's Encrypt_. To do so, it starts a temporary HTTP server to play the HTTP-challenge.
|
||||
After getting the certificate, it stores them on disk: the private key is encrypted and only readable inside the enclave.
|
||||
Then, the real HTTPS server is started using this latter and the user can now query the KMS.
|
||||
|
||||
If the initialized KMS is manually restarted while running:
|
||||
|
||||
- if the private key can be read, the HTTPS server is restarted immediately
|
||||
- otherwise, the certification process will raise an exception and the server won't start
|
||||
|
||||
At a point, the certificate will be renew automatically and the HTTPS server will be restarted immediately and automatically.
|
||||
If an error occurs during the certification process, the server stops.
|
||||
|
||||
### The database
|
||||
|
||||
The KMS database is located in the same secure enclave as multiple sqlcipher databases. Let's call _group_ a set of user sharing the same database.
|
||||
|
||||
As a consequence:
|
||||
|
||||
- These users share the same key to decrypt the database
|
||||
- They can share KMS objects between each other
|
||||
|
||||
A single KMS instance can manage several groups, that is to say, several databases.
|
||||
|
||||
The key to decrypt a database is firstly generated by the KMS and returned to the user who has queried the creation of a new _group_. The KMS will not save this key. That is to say, _Cosmian_ can't decrypt the database apart from the users queries.
|
||||
|
||||
To reply to the user queries, the KMS is expecting the user to send the key with the query.
|
||||
|
||||
If the initialized KMS is manually restarted while running:
|
||||
|
||||
- the KMS won't be able to read the databases. It will wait for the user to resend the key with its next query.
|
||||
|
||||
Because:
|
||||
|
||||
- the link between the KMS and the user is SSL-encrypted,
|
||||
- the memory of the KMS is located inside the enclave,
|
||||
- the ssl key material is located inside the enclave,
|
||||
|
||||
Then: _Cosmian_ can't get the database keys at any points.
|
||||
|
||||
### Update
|
||||
|
||||
Now, we have described how to initialize the KMS secrets and use them to communication with the end-user or the database, we will describe how it deals with these secrets when there is an update.
|
||||
|
||||
Let's remind that any modifications of the KMS source code, will generate a different binary. Therefore, the signature of that binary will be altered. As a consequence, any secrets stored in the KMS using `mr_enclave` won't be readable by the new version of the KMS. Besides, as said previously, _Cosmian_ doesn't know these secrets and can't initialize the new version of the KMS with these unknown previous secrets.
|
||||
|
||||
Let's describe how the migration of these various secrets happens.
|
||||
|
||||
To restart the KMS needs:
|
||||
|
||||
- The SSL keys and the public certificate. _Cosmian_ can't read them as the the new KMS. Therefore, the new KMS version will remove the previous keys and regenerate them. As a consequence, all new versions pushed by _Cosmian_ could be transparently known by any KMS user.
|
||||
- The sqlcipher keys. These secrets are located in the user side. Therefore, the keys will be read from the users queries.
|
||||
|
||||
### Resilience & Redundancy
|
||||
|
||||
This part cover the following scenario: we lost the KMS server and the KMS database. As a consequence, we have lost the user data and the secrets. We wan't to avoid that scenario to occur by having some sort of a database backup and secrets backup to be able to restore them if needed.
|
||||
|
||||
Let's describe how _Cosmian_ deals with this concern:
|
||||
|
||||
- The HTTPS server can be lost. _Cosmian_ will start a new one in another machine. The `mr_enclave` key will be changed. As for the update process, the new KMS version will remove the previous SSL keys and regenerate them.
|
||||
- The sqlcipher-encrypted databases are stored in plain-text on the host. It means that, if the user provides the sqlcipher key, a new KMS in another secure enclave can reload the database. The database files are written to a network volume. The replication of this volume is managed by Azure with a high level of redundancy.
|
||||
|
||||
## In-depth understanding
|
||||
|
||||
### Database
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
use clap::Args;
|
||||
|
||||
/// The configuration used by the bootstrap server.
|
||||
///
|
||||
/// The hostname is the same as the one used by the KMS server,
|
||||
/// only the port can be changed.
|
||||
#[derive(Debug, Args, Clone)]
|
||||
pub struct BootstrapServerConfig {
|
||||
/// Whether configuration should be finalized using a bootstrap server
|
||||
#[clap(long, env("KMS_USE_BOOTSTRAP_SERVER"), default_value("false"))]
|
||||
pub use_bootstrap_server: bool,
|
||||
|
||||
/// Subject as an RFC 4514 string for the RA-TLS certificate
|
||||
/// in the bootstrap server
|
||||
#[clap(
|
||||
long,
|
||||
env("KMS_BOOTSTRAP_SERVER_SUBJECT"),
|
||||
default_value("CN=cosmian.kms,O=Cosmian Tech,C=FR,L=Paris,ST=Ile-de-France")
|
||||
)]
|
||||
pub bootstrap_server_subject: String,
|
||||
|
||||
/// Number of days before the certificate expires
|
||||
#[clap(
|
||||
long,
|
||||
env("KMS_BOOTSTRAP_SERVER_EXPIRATION_DAYS"),
|
||||
default_value("365")
|
||||
)]
|
||||
pub bootstrap_server_expiration_days: u64,
|
||||
|
||||
/// The bootstrap server may be started on a specific port,
|
||||
/// The hostname will be that configured in --hostname
|
||||
#[clap(long, env("KMS_BOOTSTRAP_SERVER_PORT"), default_value("9998"))]
|
||||
pub bootstrap_server_port: u16,
|
||||
|
||||
/// Ensure RA-TLS is available and used.
|
||||
/// The server will not start if this is not the case.
|
||||
#[clap(long, env("KMS_ENSURE_RA_TLS"), default_value("false"))]
|
||||
pub ensure_ra_tls: bool,
|
||||
}
|
||||
|
||||
impl Default for BootstrapServerConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
use_bootstrap_server: false,
|
||||
bootstrap_server_subject: "CN=cosmian.kms,O=Cosmian Tech,C=FR,L=Paris,ST=Ile-de-France"
|
||||
.to_string(),
|
||||
bootstrap_server_port: 9998,
|
||||
bootstrap_server_expiration_days: 365,
|
||||
ensure_ra_tls: false,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use clap::Args;
|
||||
use tracing::info;
|
||||
|
||||
use super::WorkspaceConfig;
|
||||
use crate::{core::certbot::Certbot, error::KmsError, kms_error, result::KResult};
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct HttpsCertbotConfig {
|
||||
/// Enable TLS and use Let's Encrypt certbot to get a certificate
|
||||
#[clap(long, required(false), env("KMS_USE_CERTBOT"), default_value = "false")]
|
||||
pub use_certbot: bool,
|
||||
|
||||
/// Use TEE key generation to generate the certificate certificate (only available on tee). The value (hexadecimal) is a random salt used to derive a key from the TEE materials
|
||||
#[clap(
|
||||
long,
|
||||
required(false),
|
||||
env("KMS_CERTBOT_USE_TEE_KEY"),
|
||||
default_value = None
|
||||
)]
|
||||
pub certbot_use_tee_key: Option<String>,
|
||||
|
||||
/// The hostname of the KMS HTTPS server
|
||||
/// that will be used as the Common Name in the Let's Encrypt certificate
|
||||
#[clap(
|
||||
long,
|
||||
env("KMS_CERTBOT_HOSTNAME"),
|
||||
required(false),
|
||||
required_if_eq("use_certbot", "true"),
|
||||
default_value = ""
|
||||
)]
|
||||
pub certbot_hostname: String,
|
||||
|
||||
/// The email used during the Let's Encrypt certbot certification process
|
||||
#[clap(
|
||||
long,
|
||||
env("KMS_CERTBOT_EMAIL"),
|
||||
required(false),
|
||||
required_if_eq("use_certbot", "true"),
|
||||
default_value = ""
|
||||
)]
|
||||
pub certbot_email: String,
|
||||
|
||||
/// The folder where the KMS will store the SSL material created by certbot
|
||||
///
|
||||
/// A relative path is taken relative to the root_data_path
|
||||
#[clap(long, env = "KMS_CERTBOT_SSL_PATH", default_value = "./certbot-ssl")]
|
||||
pub certbot_ssl_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for HttpsCertbotConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
use_certbot: false,
|
||||
certbot_use_tee_key: None,
|
||||
certbot_email: String::new(),
|
||||
certbot_hostname: String::new(),
|
||||
certbot_ssl_path: std::env::temp_dir(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HttpsCertbotConfig {
|
||||
pub fn init(&self, workspace: &WorkspaceConfig) -> KResult<Certbot> {
|
||||
let certbot_ssl_path = workspace.finalize_directory(&self.certbot_ssl_path)?;
|
||||
|
||||
let http_root_path = workspace.tmp_path.join("html");
|
||||
|
||||
if !Path::new(&http_root_path).exists() {
|
||||
info!("Creating {:?}...", http_root_path);
|
||||
fs::create_dir_all(&http_root_path)?;
|
||||
}
|
||||
|
||||
Ok(Certbot::new(
|
||||
self.certbot_email.clone(),
|
||||
self.certbot_hostname.clone(),
|
||||
std::fs::canonicalize(http_root_path).map_err(|e| kms_error!(e))?,
|
||||
std::fs::canonicalize(certbot_ssl_path).map_err(|e| kms_error!(e))?,
|
||||
if let Some(salt) = &self.certbot_use_tee_key {
|
||||
Some(hex::decode(salt).map_err(|_| {
|
||||
KmsError::ConversionError(
|
||||
"`certbot_use_tee_key` value is not a hexadecimal string".to_string(),
|
||||
)
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
use std::fmt::{self};
|
||||
|
||||
use clap::Parser;
|
||||
use tee_attestation::is_running_inside_tee;
|
||||
|
||||
use super::{
|
||||
BootstrapServerConfig, DBConfig, HttpConfig, HttpsCertbotConfig, JWEConfig, JwtAuthConfig,
|
||||
TeeConfig, WorkspaceConfig,
|
||||
};
|
||||
use super::{DBConfig, HttpConfig, JWEConfig, JwtAuthConfig, WorkspaceConfig};
|
||||
|
||||
#[derive(Parser, Default)]
|
||||
#[clap(version, about, long_about = None)]
|
||||
|
@ -20,15 +16,9 @@ pub struct ClapConfig {
|
|||
#[clap(flatten)]
|
||||
pub auth: JwtAuthConfig,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub bootstrap_server: BootstrapServerConfig,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub workspace: WorkspaceConfig,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub certbot_https: HttpsCertbotConfig,
|
||||
|
||||
/// The default username to use when no authentication method is provided
|
||||
#[clap(long, env = "KMS_DEFAULT_USERNAME", default_value = "admin")]
|
||||
pub default_username: String,
|
||||
|
@ -41,9 +31,6 @@ pub struct ClapConfig {
|
|||
#[clap(flatten)]
|
||||
pub jwe: JWEConfig,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub tee: TeeConfig,
|
||||
|
||||
#[clap(long, env = "KMS_GOOGLE_CSE_KACLS_URL")]
|
||||
/// This setting enables the Google Workspace Client Side Encryption feature of this KMS server.
|
||||
///
|
||||
|
@ -56,39 +43,13 @@ pub struct ClapConfig {
|
|||
impl fmt::Debug for ClapConfig {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut x = f.debug_struct("");
|
||||
let x = if self.bootstrap_server.use_bootstrap_server {
|
||||
x.field(
|
||||
"bootstrap server port",
|
||||
&self.bootstrap_server.bootstrap_server_port,
|
||||
)
|
||||
.field(
|
||||
"bootstrap server subject",
|
||||
&self.bootstrap_server.bootstrap_server_subject,
|
||||
)
|
||||
.field(
|
||||
"bootstrap server days before expiration",
|
||||
&self.bootstrap_server.bootstrap_server_expiration_days,
|
||||
)
|
||||
} else {
|
||||
&mut x
|
||||
};
|
||||
let x = x.field("db", &self.db);
|
||||
let x = if self.auth.jwt_issuer_uri.is_some() {
|
||||
x.field("auth0", &self.auth)
|
||||
} else {
|
||||
x
|
||||
};
|
||||
let x = if is_running_inside_tee() {
|
||||
x.field("tee", &self.tee)
|
||||
} else {
|
||||
x
|
||||
};
|
||||
let x = x.field("KMS http", &self.http);
|
||||
let x = if self.certbot_https.use_certbot {
|
||||
x.field("certbot", &self.certbot_https)
|
||||
} else {
|
||||
x
|
||||
};
|
||||
let x = x.field("workspace", &self.workspace);
|
||||
let x = x.field("default username", &self.default_username);
|
||||
let x = x.field("force default username", &self.force_default_username);
|
||||
|
|
|
@ -21,8 +21,6 @@ pub struct DBConfig {
|
|||
/// A key must be supplied on every call
|
||||
/// - redis-findex: a Redis database with encrypted data and encrypted indexes thanks to Findex.
|
||||
/// The Redis url must be provided, as well as the redis-master-password and the redis-findex-label
|
||||
///
|
||||
/// The database configuration can be securely provided via the bootstrap server. Check the documentation.
|
||||
#[clap(
|
||||
long,
|
||||
env("KMS_DATABASE_TYPE"),
|
||||
|
@ -144,7 +142,6 @@ impl DBConfig {
|
|||
///
|
||||
/// # Parameters
|
||||
/// - `workspace`: The workspace configuration used to determine the public and shared paths
|
||||
/// - `use_bootstrap_server`: Whether the bootstrap server should be used to configure the database
|
||||
///
|
||||
/// # Returns
|
||||
/// - The DB parameters
|
||||
|
@ -152,11 +149,7 @@ impl DBConfig {
|
|||
/// # Errors
|
||||
/// - If both Postgres and MariaDB/MySQL URL are set
|
||||
/// - If `SQLCipher` is set along with Postgres or MariaDB/MySQL URL
|
||||
pub fn init(
|
||||
&self,
|
||||
workspace: &WorkspaceConfig,
|
||||
use_bootstrap_server: bool,
|
||||
) -> KResult<Option<DbParams>> {
|
||||
pub fn init(&self, workspace: &WorkspaceConfig) -> KResult<Option<DbParams>> {
|
||||
Ok(if let Some(database_type) = &self.database_type {
|
||||
Some(match database_type.as_str() {
|
||||
"postgresql" => {
|
||||
|
@ -199,9 +192,6 @@ impl DBConfig {
|
|||
}
|
||||
unknown => kms_bail!("Unknown database type: {unknown}"),
|
||||
})
|
||||
} else if use_bootstrap_server {
|
||||
// That is fine: the bootstrap server will be used to configure the database
|
||||
None
|
||||
} else {
|
||||
// No database configuration provided; use the default config
|
||||
let path = workspace.finalize_directory(&self.sqlite_path)?;
|
||||
|
|
|
@ -8,19 +8,15 @@ pub struct HttpConfig {
|
|||
#[clap(long, env = "KMS_PORT", default_value = "9998")]
|
||||
pub port: u16,
|
||||
|
||||
/// The KMS server (and bootstrap server) hostname
|
||||
/// The KMS server hostname
|
||||
#[clap(long, env = "KMS_HOSTNAME", default_value = "0.0.0.0")]
|
||||
pub hostname: String,
|
||||
|
||||
/// The KMS server optional PKCS#12 Certificates and Key file. If provided, this will start the server in HTTPS mode.
|
||||
///
|
||||
/// The PKCS#12 can be securely provided via the bootstrap server. Check the documentation.
|
||||
#[clap(long, env = "KMS_HTTPS_P12_FILE")]
|
||||
pub https_p12_file: Option<PathBuf>,
|
||||
|
||||
/// The password to open the PKCS#12 Certificates and Key file
|
||||
///
|
||||
/// The PKCS#12 password can be securely provided via the bootstrap server. Check the documentation.
|
||||
#[clap(long, env = "KMS_HTTPS_P12_PASSWORD", default_value = "")]
|
||||
pub https_p12_password: String,
|
||||
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
mod bootstrap_server_config;
|
||||
mod certbot_https;
|
||||
mod clap_config;
|
||||
mod db;
|
||||
mod http_config;
|
||||
mod jwe;
|
||||
mod jwt_auth_config;
|
||||
mod tee;
|
||||
mod workspace;
|
||||
|
||||
pub use bootstrap_server_config::BootstrapServerConfig;
|
||||
pub use certbot_https::HttpsCertbotConfig;
|
||||
pub use clap_config::ClapConfig;
|
||||
pub use db::DBConfig;
|
||||
pub use http_config::HttpConfig;
|
||||
pub use jwe::{JWEConfig, Jwk};
|
||||
pub use jwt_auth_config::JwtAuthConfig;
|
||||
pub use tee::TeeConfig;
|
||||
pub use workspace::WorkspaceConfig;
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use clap::Args;
|
||||
use tee_attestation::is_running_inside_tee;
|
||||
|
||||
use super::WorkspaceConfig;
|
||||
use crate::{config::params::TeeParams, kms_bail, result::KResult};
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct TeeConfig {
|
||||
/// The directory where the public key or other required files are located
|
||||
/// This path should not be encrypted by the enclave and should be directly readable from it
|
||||
///
|
||||
/// A relative path is taken relative to the `root_data_path` (see `WorkspaceConfig` struct)
|
||||
#[clap(long, env("KMS_TEE_DIR_PATH"), default_value("./tee"))]
|
||||
pub tee_dir_path: PathBuf,
|
||||
|
||||
/// The filename of the public key for SGX
|
||||
#[clap(long, env("KMS_SGX_PUBLIC_SIGNER_KEY_FILENAME"))]
|
||||
pub sgx_public_signer_key_filename: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for TeeConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tee_dir_path: PathBuf::from("./tee"),
|
||||
sgx_public_signer_key_filename: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TeeConfig {
|
||||
pub fn init(&self, workspace: &WorkspaceConfig) -> KResult<TeeParams> {
|
||||
if !is_running_inside_tee() {
|
||||
let default = Self::default();
|
||||
// these paths are never used nor created
|
||||
return Ok(TeeParams {
|
||||
sgx_public_signer_key: default.sgx_public_signer_key_filename,
|
||||
})
|
||||
}
|
||||
|
||||
if let Some(sgx_public_signer_key_filename) = &self.sgx_public_signer_key_filename {
|
||||
// finalize the enclave dir path
|
||||
let enclave_dir_path = workspace.finalize_directory(&self.tee_dir_path)?;
|
||||
|
||||
let sgx_public_signer_key = enclave_dir_path.join(sgx_public_signer_key_filename);
|
||||
if !Path::new(&sgx_public_signer_key).exists() {
|
||||
kms_bail!("Can't find '{sgx_public_signer_key:?}' as sgx_public_signer_key");
|
||||
}
|
||||
|
||||
return Ok(TeeParams {
|
||||
sgx_public_signer_key: Some(sgx_public_signer_key),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(TeeParams {
|
||||
sgx_public_signer_key: None,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -2,4 +2,4 @@ mod command_line;
|
|||
mod params;
|
||||
|
||||
pub use command_line::*;
|
||||
pub use params::{DbParams, HttpParams, ServerParams, TeeParams};
|
||||
pub use params::{DbParams, HttpParams, ServerParams};
|
||||
|
|
|
@ -1,36 +1,19 @@
|
|||
use std::{
|
||||
fmt,
|
||||
fs::File,
|
||||
io::Read,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::{fmt, fs::File, io::Read};
|
||||
|
||||
use openssl::pkcs12::{ParsedPkcs12_2, Pkcs12};
|
||||
|
||||
use crate::{
|
||||
config::{command_line::HttpsCertbotConfig, ClapConfig, WorkspaceConfig},
|
||||
core::certbot::Certbot,
|
||||
result::KResult,
|
||||
};
|
||||
use crate::{config::ClapConfig, result::KResult};
|
||||
|
||||
/// The HTTP parameters of the API server
|
||||
pub enum HttpParams {
|
||||
Certbot(Arc<Mutex<Certbot>>),
|
||||
Https(ParsedPkcs12_2),
|
||||
Http,
|
||||
}
|
||||
|
||||
impl HttpParams {
|
||||
pub fn try_from(config: &ClapConfig, workspace: &WorkspaceConfig) -> KResult<Self> {
|
||||
// certbot is the priority is that is provided
|
||||
if config.certbot_https.use_certbot {
|
||||
let certbot = Arc::new(Mutex::new(HttpsCertbotConfig::init(
|
||||
&config.certbot_https,
|
||||
workspace,
|
||||
)?));
|
||||
Ok(Self::Certbot(certbot))
|
||||
// else start in HTTPS mode if a PKCS#12 file is provided
|
||||
} else if let Some(p12_file) = &config.http.https_p12_file {
|
||||
pub fn try_from(config: &ClapConfig) -> KResult<Self> {
|
||||
// start in HTTPS mode if a PKCS#12 file is provided
|
||||
if let Some(p12_file) = &config.http.https_p12_file {
|
||||
// Open and read the file into a byte vector
|
||||
let mut file = File::open(p12_file)?;
|
||||
let mut der_bytes = Vec::new();
|
||||
|
@ -48,7 +31,7 @@ impl HttpParams {
|
|||
#[must_use]
|
||||
pub fn is_running_https(&self) -> bool {
|
||||
match self {
|
||||
Self::Certbot(_) | Self::Https(_) => true,
|
||||
Self::Https(_) => true,
|
||||
Self::Http => false,
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +40,6 @@ impl HttpParams {
|
|||
impl fmt::Debug for HttpParams {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
HttpParams::Certbot(certbot) => f.debug_tuple("Certbot").field(certbot).finish(),
|
||||
HttpParams::Https(ParsedPkcs12_2 {
|
||||
cert: Some(x509), ..
|
||||
}) => f
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
mod db_params;
|
||||
mod http_params;
|
||||
mod server_params;
|
||||
mod tee_params;
|
||||
|
||||
pub use db_params::DbParams;
|
||||
pub use http_params::HttpParams;
|
||||
pub use server_params::ServerParams;
|
||||
pub use tee_params::TeeParams;
|
||||
|
||||
use super::command_line::BootstrapServerConfig;
|
||||
|
||||
pub type BootstrapServerParams = BootstrapServerConfig;
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
use std::{
|
||||
fmt::{self},
|
||||
fs::File,
|
||||
io::Read,
|
||||
path::PathBuf,
|
||||
};
|
||||
use std::{fmt, fs::File, io::Read, path::PathBuf};
|
||||
|
||||
use alcoholic_jwt::JWKS;
|
||||
use openssl::x509::X509;
|
||||
use tee_attestation::is_running_inside_tee;
|
||||
|
||||
use super::{BootstrapServerParams, DbParams, HttpParams, TeeParams};
|
||||
use super::{DbParams, HttpParams};
|
||||
use crate::{
|
||||
config::{command_line::JWEConfig, ClapConfig},
|
||||
kms_bail,
|
||||
|
@ -38,7 +32,7 @@ pub struct ServerParams {
|
|||
/// but always use the default username instead of the one provided by the authentication method
|
||||
pub force_default_username: bool,
|
||||
|
||||
/// The DB parameters may be supplied on the command line or via the bootstrap server
|
||||
/// The DB parameters may be supplied on the command line
|
||||
pub db_params: Option<DbParams>,
|
||||
|
||||
/// Whether to clear the database on start
|
||||
|
@ -48,26 +42,11 @@ pub struct ServerParams {
|
|||
|
||||
pub port: u16,
|
||||
|
||||
// /// The provided PKCS#12 when HTTPS is enabled
|
||||
// pub server_pkcs_12: Option<ParsedPkcs12_2>,
|
||||
|
||||
// /// The certbot engine if certbot is enabled
|
||||
// pub certbot: Option<Arc<Mutex<Certbot>>>,
|
||||
pub http_params: HttpParams,
|
||||
|
||||
/// The tee parameters when running inside a tee
|
||||
pub tee_params: TeeParams,
|
||||
|
||||
/// The certificate used to verify the client TLS certificates
|
||||
/// used for authentication
|
||||
pub verify_cert: Option<X509>,
|
||||
|
||||
/// Use a bootstrap server (inside a tee for instance)
|
||||
pub bootstrap_server_params: BootstrapServerParams,
|
||||
|
||||
/// Ensure RA-TLS is available and used.
|
||||
/// The server will not start if this is not the case.
|
||||
pub ensure_ra_tls: bool,
|
||||
pub client_cert: Option<X509>,
|
||||
|
||||
/// This setting enables the Google Workspace Client Side Encryption feature of this KMS server.
|
||||
///
|
||||
|
@ -83,7 +62,7 @@ impl ServerParams {
|
|||
let workspace = conf.workspace.init()?;
|
||||
|
||||
// The HTTP/HTTPS parameters
|
||||
let http_params = HttpParams::try_from(conf, &workspace)?;
|
||||
let http_params = HttpParams::try_from(conf)?;
|
||||
|
||||
// Should we verify the client TLS certificates?
|
||||
let verify_cert = if let Some(authority_cert_file) = &conf.http.authority_cert_file {
|
||||
|
@ -104,19 +83,14 @@ impl ServerParams {
|
|||
jwt_issuer_uri: conf.auth.jwt_issuer_uri.clone(),
|
||||
jwe_config: conf.jwe.clone(),
|
||||
jwt_audience: conf.auth.jwt_audience.clone(),
|
||||
db_params: conf
|
||||
.db
|
||||
.init(&workspace, conf.bootstrap_server.use_bootstrap_server)?,
|
||||
db_params: conf.db.init(&workspace)?,
|
||||
clear_db_on_start: conf.db.clear_database,
|
||||
hostname: conf.http.hostname.clone(),
|
||||
port: conf.http.port,
|
||||
http_params: HttpParams::try_from(conf, &workspace)?,
|
||||
tee_params: conf.tee.init(&workspace)?,
|
||||
http_params: HttpParams::try_from(conf)?,
|
||||
default_username: conf.default_username.clone(),
|
||||
force_default_username: conf.force_default_username,
|
||||
verify_cert,
|
||||
bootstrap_server_params: conf.bootstrap_server.clone(),
|
||||
ensure_ra_tls: conf.bootstrap_server.ensure_ra_tls,
|
||||
client_cert: verify_cert,
|
||||
google_cse_kacls_url: conf.google_cse_kacls_url.clone(),
|
||||
};
|
||||
Ok(server_conf)
|
||||
|
@ -137,31 +111,6 @@ impl ServerParams {
|
|||
impl fmt::Debug for ServerParams {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut x = f.debug_struct("");
|
||||
let x = if self.bootstrap_server_params.use_bootstrap_server {
|
||||
x.field(
|
||||
"bootstrap server url",
|
||||
&format!(
|
||||
"https://{}:{}",
|
||||
&self.hostname, &self.bootstrap_server_params.bootstrap_server_port
|
||||
),
|
||||
)
|
||||
.field(
|
||||
"bootstrap server subject",
|
||||
&self.bootstrap_server_params.bootstrap_server_subject,
|
||||
)
|
||||
.field(
|
||||
"bootstrap server days before expiration",
|
||||
&self
|
||||
.bootstrap_server_params
|
||||
.bootstrap_server_expiration_days,
|
||||
)
|
||||
.field(
|
||||
"bootstrap server ensure RA-TLS",
|
||||
&self.bootstrap_server_params.ensure_ra_tls,
|
||||
)
|
||||
} else {
|
||||
&mut x
|
||||
};
|
||||
let x = x
|
||||
.field(
|
||||
"kms_url",
|
||||
|
@ -185,7 +134,7 @@ impl fmt::Debug for ServerParams {
|
|||
} else {
|
||||
x
|
||||
};
|
||||
let x = if let Some(verify_cert) = &self.verify_cert {
|
||||
let x = if let Some(verify_cert) = &self.client_cert {
|
||||
x.field("verify_cert CN", verify_cert.subject_name())
|
||||
} else {
|
||||
x
|
||||
|
@ -194,11 +143,6 @@ impl fmt::Debug for ServerParams {
|
|||
.field("default_username", &self.default_username)
|
||||
.field("force_default_username", &self.force_default_username);
|
||||
let x = x.field("http_params", &self.http_params);
|
||||
let x = if is_running_inside_tee() {
|
||||
x.field("tee_params", &self.tee_params)
|
||||
} else {
|
||||
x
|
||||
};
|
||||
x.finish()
|
||||
}
|
||||
}
|
||||
|
@ -220,10 +164,7 @@ impl Clone for ServerParams {
|
|||
hostname: self.hostname.clone(),
|
||||
port: self.port,
|
||||
http_params: HttpParams::Http,
|
||||
tee_params: self.tee_params.clone(),
|
||||
verify_cert: self.verify_cert.clone(),
|
||||
bootstrap_server_params: self.bootstrap_server_params.clone(),
|
||||
ensure_ra_tls: self.ensure_ra_tls,
|
||||
client_cert: self.client_cert.clone(),
|
||||
google_cse_kacls_url: self.google_cse_kacls_url.clone(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TeeParams {
|
||||
// contains the path to the sgx signer public key
|
||||
pub sgx_public_signer_key: Option<PathBuf>,
|
||||
}
|
|
@ -1,249 +0,0 @@
|
|||
use std::{
|
||||
fmt, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use acme_lib::{
|
||||
create_p384_key, persist::FilePersist, Account, Certificate, Directory, DirectoryUrl,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
use openssl::{
|
||||
bn::{BigNum, BigNumContext},
|
||||
ec::{EcGroup, EcKey, EcPoint},
|
||||
nid::Nid,
|
||||
pkey::{PKey, Private},
|
||||
x509::X509,
|
||||
};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use openssl::{
|
||||
pkey::{PKey, Private},
|
||||
x509::X509,
|
||||
};
|
||||
|
||||
use crate::{error::KmsError, kms_bail, result::KResult};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Certbot {
|
||||
pub days_threshold_before_renew: i64,
|
||||
pub email: String,
|
||||
pub common_name: String,
|
||||
pub http_root_path: PathBuf,
|
||||
pub keys_path: PathBuf,
|
||||
pub use_tee_key: Option<Vec<u8>>,
|
||||
account: Option<Account<FilePersist>>,
|
||||
certificate: Option<Certificate>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Certbot {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Certbot")
|
||||
.field(
|
||||
"days_threshold_before_renew",
|
||||
&self.days_threshold_before_renew,
|
||||
)
|
||||
.field("email", &self.email)
|
||||
.field("common name", &self.common_name)
|
||||
.field("http_root_path", &self.http_root_path)
|
||||
.field("keys_path", &self.keys_path)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Certbot {
|
||||
fn default() -> Self {
|
||||
Self::new(
|
||||
String::new(),
|
||||
String::new(),
|
||||
PathBuf::from(""),
|
||||
PathBuf::from(""),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Certbot {
|
||||
pub fn new(
|
||||
email: String,
|
||||
common_name: String,
|
||||
http_root_path: PathBuf,
|
||||
keys_path: PathBuf,
|
||||
use_tee_key: Option<Vec<u8>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
days_threshold_before_renew: 15,
|
||||
email,
|
||||
common_name,
|
||||
http_root_path,
|
||||
keys_path,
|
||||
use_tee_key,
|
||||
account: None,
|
||||
certificate: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self) -> KResult<()> {
|
||||
#[cfg(feature = "insecure")]
|
||||
let url = DirectoryUrl::LetsEncryptStaging;
|
||||
|
||||
#[cfg(not(feature = "insecure"))]
|
||||
let url = DirectoryUrl::LetsEncrypt;
|
||||
|
||||
// Save/load keys and certificates to current dir.
|
||||
let persist = FilePersist::new(&self.keys_path);
|
||||
|
||||
// Create a directory entrypoint.
|
||||
let dir = Directory::from_url(persist, url)?;
|
||||
|
||||
let acc = dir.account(&self.email)?;
|
||||
|
||||
self.certificate = acc.certificate(&self.common_name)?;
|
||||
|
||||
self.account = Some(acc);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check if the certificate exists and is valid
|
||||
pub fn check(&self) -> bool {
|
||||
match &self.certificate {
|
||||
Some(certificate) => certificate.valid_days_left() > self.days_threshold_before_renew,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Return the number of days before the certificate expired
|
||||
pub fn get_days_before_expiration(&self) -> KResult<i64> {
|
||||
match &self.certificate {
|
||||
Some(certificate) => Ok(certificate.valid_days_left()),
|
||||
_ => Ok(0),
|
||||
}
|
||||
}
|
||||
|
||||
// Return the number of days before the certificate has to be renewed
|
||||
pub fn get_days_before_renew(&self) -> KResult<i64> {
|
||||
Ok(self.get_days_before_expiration()? - self.days_threshold_before_renew)
|
||||
}
|
||||
|
||||
// Get the certificate as standard OpenSSL objects
|
||||
pub fn get_cert(&self) -> KResult<(PKey<Private>, Vec<X509>)> {
|
||||
if let Some(certificate) = &self.certificate {
|
||||
return Ok((
|
||||
PKey::private_key_from_pem(certificate.private_key().as_bytes())?,
|
||||
X509::stack_from_pem(certificate.certificate().as_bytes())?,
|
||||
))
|
||||
}
|
||||
kms_bail!("Certificate can't be found...");
|
||||
}
|
||||
|
||||
// Get the certificate as ACME objects
|
||||
pub fn get_raw_cert(&self) -> KResult<(&str, &str)> {
|
||||
if let Some(certificate) = &self.certificate {
|
||||
return Ok((certificate.private_key(), certificate.certificate()))
|
||||
}
|
||||
kms_bail!("Certificate can't be found...");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn generate_private_key(&self) -> KResult<PKey<Private>> {
|
||||
if let Some(salt) = &self.use_tee_key {
|
||||
let key = tee_attestation::get_key(Some(salt))?;
|
||||
let private_number = BigNum::from_slice(&key)?;
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
|
||||
|
||||
let mut public_point = EcPoint::new(&group)?;
|
||||
let ctx = BigNumContext::new()?;
|
||||
public_point.mul_generator(&group, &private_number, &ctx)?;
|
||||
|
||||
let pri_key_ec =
|
||||
EcKey::from_private_components(&group, &private_number, &public_point)?;
|
||||
Ok(PKey::from_ec_key(pri_key_ec)?)
|
||||
} else {
|
||||
Ok(create_p384_key())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn generate_private_key(&self) -> KResult<PKey<Private>> {
|
||||
Ok(create_p384_key())
|
||||
}
|
||||
|
||||
pub fn request_cert(&mut self) -> KResult<()> {
|
||||
let pkey_pri = self.generate_private_key()?;
|
||||
|
||||
let acc = self
|
||||
.account
|
||||
.as_ref()
|
||||
.ok_or_else(|| KmsError::ServerError("Account shouldn't be None".to_string()))?;
|
||||
|
||||
// Order a new TLS certificate for a domain.
|
||||
let mut ord_new = acc.new_order(&self.common_name, &[])?;
|
||||
|
||||
let target = Path::new(&self.http_root_path).join(".well-known/acme-challenge/");
|
||||
let target_parent = Path::new(&self.http_root_path).join(".well-known");
|
||||
|
||||
// If the ownership of the domain(s) has already been
|
||||
// authorized in a previous order, you might be able to
|
||||
// skip validation. The ACME API provider decides.
|
||||
let ord_csr = loop {
|
||||
// are we done?
|
||||
if let Some(ord_csr) = ord_new.confirm_validations() {
|
||||
break ord_csr
|
||||
}
|
||||
|
||||
// Get the possible authorizations (for a single domain
|
||||
// this will only be one element).
|
||||
let auths = ord_new.authorizations()?;
|
||||
|
||||
// For HTTP, the challenge is a text file that needs to
|
||||
// be placed in your web server's root:
|
||||
//
|
||||
// /var/www/.well-known/acme-challenge/<token>
|
||||
//
|
||||
// The important thing is that it's accessible over the
|
||||
// web for the domain(s) you are trying to get a
|
||||
// certificate for:
|
||||
//
|
||||
// http://mydomain.io/.well-known/acme-challenge/<token>
|
||||
let chall = auths[0].http_challenge();
|
||||
|
||||
// The token is the filename.
|
||||
let token = chall.http_token();
|
||||
|
||||
// The proof is the contents of the file
|
||||
let proof = chall.http_proof();
|
||||
|
||||
// Update my web server
|
||||
fs::create_dir_all(&target)?;
|
||||
fs::write(target.join(token), proof).expect("Unable to write the token file");
|
||||
|
||||
// After the file is accessible from the web,
|
||||
// this tells the ACME API to start checking the
|
||||
// existence of the proof.
|
||||
//
|
||||
// The order at ACME will change status to either
|
||||
// confirm ownership of the domain, or fail due to the
|
||||
// not finding the proof. To see the change, we poll
|
||||
// the API with 5000 milliseconds wait between.
|
||||
chall.validate(5000)?;
|
||||
|
||||
// Update the state against the ACME API.
|
||||
ord_new.refresh()?;
|
||||
|
||||
// Clean the .well-known
|
||||
#[allow(clippy::needless_borrow)]
|
||||
fs::remove_dir_all(&target_parent)?;
|
||||
};
|
||||
|
||||
// Submit the CSR. This causes the ACME provider to enter a
|
||||
// state of "processing" that must be polled until the
|
||||
// certificate is either issued or rejected. Again we poll
|
||||
// for the status change.
|
||||
let ord_cert = ord_csr.finalize_pkey(pkey_pri, 5000)?;
|
||||
|
||||
// Now download the certificate. Also stores the cert in
|
||||
// the persistence.
|
||||
self.certificate = Some(ord_cert.download_and_save_cert()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -18,18 +18,25 @@ use cosmian_kmip::{
|
|||
},
|
||||
openssl::{kmip_private_key_to_openssl, kmip_public_key_to_openssl},
|
||||
};
|
||||
#[cfg(not(feature = "fips"))]
|
||||
use cosmian_kms_utils::crypto::curve_25519::operation::create_p192_key_pair;
|
||||
use cosmian_kms_utils::{
|
||||
access::ExtraDatabaseParams,
|
||||
crypto::{
|
||||
cover_crypt::{decryption::CovercryptDecryption, encryption::CoverCryptEncryption},
|
||||
curve_25519::operation::{create_ed25519_key_pair, create_x25519_key_pair},
|
||||
curve_25519::operation::{
|
||||
create_ed25519_key_pair, create_p224_key_pair, create_p256_key_pair,
|
||||
create_p384_key_pair, create_p521_key_pair, create_x25519_key_pair,
|
||||
},
|
||||
hybrid_encryption::{HybridDecryptionSystem, HybridEncryptionSystem},
|
||||
symmetric::{create_symmetric_key, AesGcmSystem},
|
||||
},
|
||||
tagging::{check_user_tags, get_tags, remove_tags},
|
||||
DecryptionSystem, EncryptionSystem, KeyPair,
|
||||
};
|
||||
use tracing::{debug, log::warn, trace};
|
||||
#[cfg(not(feature = "fips"))]
|
||||
use tracing::warn;
|
||||
use tracing::{debug, trace};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use super::{cover_crypt::create_user_decryption_key, KMS};
|
||||
|
@ -382,17 +389,32 @@ impl KMS {
|
|||
.cryptographic_domain_parameters
|
||||
.unwrap_or_default();
|
||||
match dp.recommended_curve.unwrap_or_default() {
|
||||
// TODO - #[cfg(not(feature = "fips"))]
|
||||
RecommendedCurve::CURVE25519 => {
|
||||
let mut rng = self.rng.lock().expect("RNG lock poisoned");
|
||||
create_x25519_key_pair(&mut *rng, private_key_uid, public_key_uid)
|
||||
create_x25519_key_pair(private_key_uid, public_key_uid)
|
||||
}
|
||||
#[cfg(not(feature = "fips"))]
|
||||
RecommendedCurve::P192 => create_p192_key_pair(private_key_uid, public_key_uid),
|
||||
RecommendedCurve::P224 => create_p224_key_pair(private_key_uid, public_key_uid),
|
||||
RecommendedCurve::P256 => create_p256_key_pair(private_key_uid, public_key_uid),
|
||||
RecommendedCurve::P384 => create_p384_key_pair(private_key_uid, public_key_uid),
|
||||
RecommendedCurve::P521 => create_p521_key_pair(private_key_uid, public_key_uid),
|
||||
#[cfg(not(feature = "fips"))]
|
||||
RecommendedCurve::CURVEED25519 => {
|
||||
warn!(
|
||||
"An Edwards Keypair on curve 25519 should not be requested to perform \
|
||||
ECDH. Creating anyway as it can be converted to Montgomery X25519"
|
||||
ECDH. Creating anyway."
|
||||
);
|
||||
let mut rng = self.rng.lock().expect("RNG lock poisoned");
|
||||
create_ed25519_key_pair(&mut *rng, private_key_uid, public_key_uid)
|
||||
create_ed25519_key_pair(private_key_uid, public_key_uid)
|
||||
}
|
||||
#[cfg(feature = "fips")]
|
||||
// Ed25519 not allowed for ECDH.
|
||||
// see NIST.SP.800-186 - Section 3.1.2 table 2.
|
||||
RecommendedCurve::CURVEED25519 => {
|
||||
kms_not_supported!(
|
||||
"An Edwards Keypair on curve 25519 should not be requested to perform \
|
||||
ECDH in FIPS mode."
|
||||
)
|
||||
}
|
||||
other => kms_not_supported!(
|
||||
"Generation of Key Pair for curve: {other:?}, is not supported"
|
||||
|
@ -400,8 +422,7 @@ impl KMS {
|
|||
}
|
||||
}
|
||||
CryptographicAlgorithm::Ed25519 => {
|
||||
let mut rng = self.rng.lock().expect("RNG lock poisoned");
|
||||
create_ed25519_key_pair(&mut *rng, private_key_uid, public_key_uid)
|
||||
create_ed25519_key_pair(private_key_uid, public_key_uid)
|
||||
}
|
||||
CryptographicAlgorithm::CoverCrypt => {
|
||||
cosmian_kms_utils::crypto::cover_crypt::master_keys::create_master_keypair(
|
||||
|
|
|
@ -56,18 +56,6 @@ impl KMS {
|
|||
/// - the server server certificate cannot be read
|
||||
pub fn get_server_x509_certificate(&self) -> KResult<Option<Vec<u8>>> {
|
||||
match &self.params.http_params {
|
||||
crate::config::HttpParams::Certbot(certbot) => {
|
||||
let cert = certbot.lock().expect("can't lock certificate mutex");
|
||||
let (_, certificate) = cert.get_cert()?;
|
||||
Ok(Some(
|
||||
certificate
|
||||
.first()
|
||||
.ok_or(KmsError::Certificate(
|
||||
"No leaf certificate in the KMS certificate chain".to_owned(),
|
||||
))?
|
||||
.to_pem()?,
|
||||
))
|
||||
}
|
||||
crate::config::HttpParams::Https(p12) => {
|
||||
let pem = p12
|
||||
.cert
|
||||
|
@ -83,20 +71,6 @@ impl KMS {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the enclave public key
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns a `KResult` with a `Error` if the enclave public key file cannot be read
|
||||
pub fn get_sgx_enclave_public_key(&self) -> KResult<String> {
|
||||
if let Some(sgx_public_signer_key) = &self.params.tee_params.sgx_public_signer_key {
|
||||
return Ok(fs::read_to_string(sgx_public_signer_key)?)
|
||||
}
|
||||
|
||||
Err(KmsError::ItemNotFound(
|
||||
"No SGX signer public key".to_owned(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Adds a new encrypted `SQLite` database to the KMS server.
|
||||
///
|
||||
/// # Returns
|
||||
|
@ -148,23 +122,6 @@ impl KMS {
|
|||
));
|
||||
}
|
||||
|
||||
/// Return the enclave quote
|
||||
///
|
||||
/// This service is not available if the server is not running inside an enclave
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_attestation_report(&self, nonce: [u8; 32]) -> KResult<String> {
|
||||
let certificate = self.get_server_x509_certificate()?;
|
||||
|
||||
if let Some(certificate) = certificate {
|
||||
let report_data = cosmian_kms_utils::tee::forge_report_data(&nonce, &certificate)?;
|
||||
return Ok(b64.encode(tee_attestation::get_quote(&report_data)?))
|
||||
}
|
||||
|
||||
Err(KmsError::NotSupported(
|
||||
"Can't get a report attestation without a configured certificate".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
/// This operation requests the server to Import a Managed Object specified
|
||||
/// by its Unique Identifier. The request specifies the object being
|
||||
/// imported and all the attributes to be assigned to the object. The
|
||||
|
@ -571,7 +528,7 @@ impl KMS {
|
|||
let uid = access
|
||||
.unique_identifier
|
||||
.as_ref()
|
||||
.ok_or_else(|| KmsError::UnsupportedPlaceholder)?
|
||||
.ok_or(KmsError::UnsupportedPlaceholder)?
|
||||
.as_str()
|
||||
.context("unique_identifier is not a string")?;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
pub(crate) mod certbot;
|
||||
pub(crate) mod certificate;
|
||||
pub(crate) mod cover_crypt;
|
||||
pub(crate) mod implementation;
|
||||
|
|
|
@ -96,11 +96,10 @@ pub async fn wrap_key(
|
|||
};
|
||||
|
||||
// wrap the key based on the encoding
|
||||
let mut rng = kms.rng.lock().expect("could not acquire a lock on the rng");
|
||||
match encoding {
|
||||
EncodingOption::TTLVEncoding => {
|
||||
let plaintext = serde_json::to_vec(&object_key_block.key_value)?;
|
||||
let ciphertext = encrypt_bytes(&mut *rng, &wrapping_key.object, &plaintext)?;
|
||||
let ciphertext = encrypt_bytes(&wrapping_key.object, &plaintext)?;
|
||||
object_key_block.key_value = KeyValue {
|
||||
key_material: KeyMaterial::ByteString(ciphertext),
|
||||
// not clear whether this should be filled or not
|
||||
|
@ -109,7 +108,7 @@ pub async fn wrap_key(
|
|||
}
|
||||
EncodingOption::NoEncoding => {
|
||||
let plaintext = object_key_block.key_bytes()?;
|
||||
let ciphertext = encrypt_bytes(&mut *rng, &wrapping_key.object, &plaintext)?;
|
||||
let ciphertext = encrypt_bytes(&wrapping_key.object, &plaintext)?;
|
||||
object_key_block.key_value.key_material = KeyMaterial::ByteString(ciphertext);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -60,10 +60,6 @@ pub enum KmsError {
|
|||
#[error("Unexpected server error: {0}")]
|
||||
ServerError(String),
|
||||
|
||||
// Any errors related to a bad behavior of the server concerning the SGX environment
|
||||
#[error(transparent)]
|
||||
TeeAttestationError(#[from] tee_attestation::error::Error),
|
||||
|
||||
// Any actions of the user which is not allowed
|
||||
#[error("Access denied: {0}")]
|
||||
Unauthorized(String),
|
||||
|
@ -155,12 +151,6 @@ impl From<openssl::error::ErrorStack> for KmsError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<acme_lib::Error> for KmsError {
|
||||
fn from(e: acme_lib::Error) -> Self {
|
||||
Self::ServerError(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for KmsError {
|
||||
fn from(e: serde_json::Error) -> Self {
|
||||
Self::InvalidRequest(e.to_string())
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc, Arc, Mutex, RwLock,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
use std::sync::{mpsc, Arc, RwLock};
|
||||
|
||||
use actix_cors::Cors;
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_web::{
|
||||
dev::ServerHandle,
|
||||
middleware::Condition,
|
||||
rt::{spawn, time::sleep},
|
||||
web::{self, Data, JsonConfig, PayloadConfig},
|
||||
App, HttpServer,
|
||||
};
|
||||
|
@ -19,12 +12,11 @@ use openssl::{
|
|||
ssl::{SslAcceptor, SslAcceptorBuilder, SslMethod, SslVerifyMode},
|
||||
x509::store::X509StoreBuilder,
|
||||
};
|
||||
use tee_attestation::is_running_inside_tee;
|
||||
use tracing::{debug, error, info};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
config::{self, HttpParams, ServerParams},
|
||||
core::{certbot::Certbot, KMS},
|
||||
config::{self, ServerParams},
|
||||
core::KMS,
|
||||
kms_bail, kms_error,
|
||||
middlewares::{
|
||||
ssl_auth::{extract_peer_certificate, SslAuth},
|
||||
|
@ -43,7 +35,6 @@ use crate::{
|
|||
/// The server is started using one of three methods:
|
||||
/// 1. Plain HTTP,
|
||||
/// 2. HTTPS with PKCS#12,
|
||||
/// 3. HTTPS with certbot.
|
||||
///
|
||||
/// The method used depends on the server settings specified in the `ServerParams` instance provided.
|
||||
///
|
||||
|
@ -62,9 +53,6 @@ pub async fn start_kms_server(
|
|||
// Log the server configuration
|
||||
info!("KMS Server configuration: {:#?}", server_params);
|
||||
match &server_params.http_params {
|
||||
config::HttpParams::Certbot(_) => {
|
||||
start_certbot_https_kms_server(server_params, kms_server_handle_tx).await
|
||||
}
|
||||
config::HttpParams::Https(_) => {
|
||||
start_https_kms_server(server_params, kms_server_handle_tx).await
|
||||
}
|
||||
|
@ -147,7 +135,7 @@ async fn start_https_kms_server(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(verify_cert) = &server_params.verify_cert {
|
||||
if let Some(verify_cert) = &server_params.client_cert {
|
||||
// This line sets the mode to verify peer (client) certificates
|
||||
builder.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT);
|
||||
let mut store_builder = X509StoreBuilder::new()?;
|
||||
|
@ -170,195 +158,6 @@ async fn start_https_kms_server(
|
|||
server.await.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Start and https server with the ability to renew its certificates
|
||||
async fn start_auto_renew_https(
|
||||
server_params: ServerParams,
|
||||
certbot: &Arc<Mutex<Certbot>>,
|
||||
server_handle_transmitter: Option<mpsc::Sender<ServerHandle>>,
|
||||
) -> KResult<()> {
|
||||
let kms_server = Arc::new(KMSServer::instantiate(server_params).await?);
|
||||
|
||||
// The loop is designed to restart the server in case it stops.
|
||||
// It stops when we renew the certificates
|
||||
loop {
|
||||
// Define an HTTPS server
|
||||
let (pk, x509) = certbot
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.get_cert()?;
|
||||
|
||||
debug!("Building the HTTPS server... ");
|
||||
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
|
||||
builder.set_private_key(&pk)?;
|
||||
builder.set_certificate(&x509[0])?;
|
||||
for x in x509 {
|
||||
builder.add_extra_chain_cert(x)?;
|
||||
}
|
||||
|
||||
let server = prepare_kms_server(kms_server.clone(), Some(builder)).await?;
|
||||
|
||||
// send the server handle to the caller
|
||||
if let Some(tx) = &server_handle_transmitter {
|
||||
tx.send(server.handle())?;
|
||||
}
|
||||
|
||||
let restart = Arc::new(AtomicBool::new(false));
|
||||
let restart_me = Arc::clone(&restart);
|
||||
let srv = server.handle();
|
||||
let cert_copy = Arc::clone(certbot);
|
||||
|
||||
// Define and start the thread renewing the certificate
|
||||
spawn(async move {
|
||||
let days_before_renew = cert_copy
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.get_days_before_renew();
|
||||
let renew_in = match days_before_renew {
|
||||
Ok(x) => x,
|
||||
Err(error) => {
|
||||
error!("Error when asking for renewing the certificate {error}");
|
||||
0 // force the renew
|
||||
}
|
||||
};
|
||||
|
||||
// Wait for the renew date.
|
||||
if renew_in > 0 {
|
||||
info!("Waiting {renew_in} days before renewing the certificate!");
|
||||
sleep(Duration::from_secs(renew_in as u64 * 3600 * 24)).await;
|
||||
}
|
||||
|
||||
// It's time to renew!!
|
||||
info!("Updating certificate now...");
|
||||
let request_cert = cert_copy
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.request_cert();
|
||||
match request_cert {
|
||||
Ok(()) => restart_me.store(true, Ordering::Relaxed),
|
||||
Err(error) => {
|
||||
error!("Error when renewing the certificate {error}");
|
||||
restart_me.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
info!("Stopping the HTTPS server...");
|
||||
// Stop the HTTPS server. We don't need it anymore
|
||||
srv.stop(true).await;
|
||||
});
|
||||
|
||||
// Run server until stopped (either by ctrl-c or stopped by the previous thread)
|
||||
info!("Starting the HTTPS KMS server...");
|
||||
server.await?;
|
||||
|
||||
// We reach that part of the code when the thread renewing the certificates stops.
|
||||
if restart.load(Ordering::Relaxed) {
|
||||
restart.store(false, Ordering::Relaxed);
|
||||
} else {
|
||||
// If we reach that point, we don't want to restart.
|
||||
// Contact the administrator
|
||||
error!("Can't restart the HTTPS server (no valid certificate)...");
|
||||
kms_bail!("Can't restart the HTTPS server (no valid certificate)...")
|
||||
|
||||
// Note: we could decide another behavior such as:
|
||||
// Let the server up. Then the web browser or the wget will raise a security error the user can ignore
|
||||
// That way, we don't stop our service.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_certbot_https_kms_server(
|
||||
server_params: ServerParams,
|
||||
server_handle_transmitter: Option<mpsc::Sender<ServerHandle>>,
|
||||
) -> KResult<()> {
|
||||
// Before starting any servers, check the status of our SSL certificates
|
||||
let certbot = match &server_params.http_params {
|
||||
HttpParams::Certbot(certbot) => certbot.clone(),
|
||||
_ => kms_bail!("trying to start a TLS server but certbot is not used !"),
|
||||
};
|
||||
|
||||
debug!("Initializing certbot");
|
||||
// Recover the previous certificate if exist
|
||||
certbot
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.init()?;
|
||||
|
||||
debug!("Checking certificates...");
|
||||
let mut has_valid_cert = certbot
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.check();
|
||||
|
||||
let http_root_path = certbot
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.http_root_path
|
||||
.clone();
|
||||
|
||||
if !has_valid_cert {
|
||||
info!("No valid certificate found!");
|
||||
info!("Starting certification process...");
|
||||
|
||||
// Start a HTTP server, to negotiate a certificate
|
||||
let server = HttpServer::new(move || {
|
||||
App::new().service(actix_files::Files::new("/", &http_root_path).use_hidden_files())
|
||||
})
|
||||
.workers(1)
|
||||
.bind(("0.0.0.0", 80))?
|
||||
.run();
|
||||
// The server is not started yet here!
|
||||
|
||||
let succeed = Arc::new(AtomicBool::new(false));
|
||||
let succeed_me = Arc::clone(&succeed);
|
||||
let srv = server.handle();
|
||||
let cert_copy = Arc::clone(&certbot);
|
||||
|
||||
spawn(async move {
|
||||
// Generate the certificate in another thread
|
||||
info!("Requesting acme...");
|
||||
let request_cert = cert_copy
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.request_cert();
|
||||
match request_cert {
|
||||
Ok(()) => succeed_me.store(true, Ordering::Relaxed),
|
||||
Err(error) => {
|
||||
error!("Error when generating the certificate: {error}");
|
||||
succeed_me.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the HTTP server. We don't need it anymore
|
||||
srv.stop(true).await;
|
||||
});
|
||||
|
||||
// Run server until stopped (either by ctrl-c or stopped by the previous thread)
|
||||
info!("Starting the HTTP KMS server...");
|
||||
server.await?;
|
||||
|
||||
// Note: cert_copy is a ref to cert. So `cert.certificates` contains the new certificates
|
||||
// Therefore, we do not need to call `cert.init()`. That way, we avoid several acme useless queries
|
||||
has_valid_cert = succeed.load(Ordering::Relaxed)
|
||||
&& certbot
|
||||
.lock()
|
||||
.expect("can't lock certificate mutex")
|
||||
.check();
|
||||
|
||||
info!("Stop the HTTP server");
|
||||
}
|
||||
|
||||
if has_valid_cert {
|
||||
// Use it and start SSL Server
|
||||
info!("Certificate is valid");
|
||||
start_auto_renew_https(server_params, &certbot, server_handle_transmitter).await?;
|
||||
} else {
|
||||
error!("Abort program, failed to get a valid certificate");
|
||||
kms_bail!("Abort program, failed to get a valid certificate")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
* This function prepares a server for the application. It creates an `HttpServer` instance,
|
||||
* configures the routes for the application, and sets the request timeout. The server can be
|
||||
|
@ -403,8 +202,8 @@ pub async fn prepare_kms_server(
|
|||
(false, None)
|
||||
};
|
||||
// Determine if Client Cert Auth should be used for authentication.
|
||||
let use_cert_auth = kms_server.params.verify_cert.is_some();
|
||||
// Determine if the application is running inside an enclave.
|
||||
let use_cert_auth = kms_server.params.client_cert.is_some();
|
||||
|
||||
// Determine if the application is using an encrypted SQLite database.
|
||||
let is_using_sqlite_enc = matches!(
|
||||
kms_server.params.db_params,
|
||||
|
@ -479,14 +278,6 @@ pub async fn prepare_kms_server(
|
|||
} else {
|
||||
default_scope
|
||||
};
|
||||
// The default scope is extended with the /tee endpoints if the application is running inside an enclave.
|
||||
let default_scope = if is_running_inside_tee() {
|
||||
default_scope
|
||||
.service(routes::tee::get_enclave_public_key)
|
||||
.service(routes::tee::get_attestation_report)
|
||||
} else {
|
||||
default_scope
|
||||
};
|
||||
|
||||
app.service(default_scope)
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//! since it is declared, all the modules in other Files
|
||||
//! will be resolved against the lib. So everything is exported
|
||||
|
||||
pub mod bootstrap_server;
|
||||
pub mod config;
|
||||
pub mod core;
|
||||
pub mod database;
|
||||
|
@ -12,30 +11,7 @@ pub mod middlewares;
|
|||
pub mod result;
|
||||
pub mod routes;
|
||||
|
||||
use std::{pin::Pin, sync::mpsc};
|
||||
|
||||
use actix_web::dev::ServerHandle;
|
||||
use bootstrap_server::start_kms_server_using_bootstrap_server;
|
||||
use config::ServerParams;
|
||||
pub use database::KMSServer;
|
||||
use futures::Future;
|
||||
use kms_server::start_kms_server;
|
||||
use result::KResult;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[must_use]
|
||||
pub fn start_server(
|
||||
server_params: ServerParams,
|
||||
kms_server_handle_tx: Option<mpsc::Sender<ServerHandle>>,
|
||||
) -> Pin<Box<dyn Future<Output = KResult<()>>>> {
|
||||
if server_params.bootstrap_server_params.use_bootstrap_server {
|
||||
Box::pin(start_kms_server_using_bootstrap_server(
|
||||
server_params,
|
||||
kms_server_handle_tx,
|
||||
))
|
||||
} else {
|
||||
Box::pin(start_kms_server(server_params, kms_server_handle_tx))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use cosmian_kms_server::{
|
||||
config::{ClapConfig, ServerParams},
|
||||
kms_server::start_kms_server,
|
||||
result::KResult,
|
||||
start_server,
|
||||
};
|
||||
use dotenvy::dotenv;
|
||||
use tracing::debug;
|
||||
|
@ -18,9 +18,6 @@ use clap::Parser;
|
|||
///
|
||||
/// This function sets up the necessary environment variables and logging options,
|
||||
/// then parses the command line arguments using [`ClapConfig::parse()`](https://docs.rs/clap/latest/clap/struct.ClapConfig.html#method.parse).
|
||||
///
|
||||
/// After that, it starts the correct server based on
|
||||
/// whether the bootstrap server should be used or not (using `start_bootstrap_server()` or `start_kms_server()`, respectively).
|
||||
#[actix_web::main]
|
||||
async fn main() -> KResult<()> {
|
||||
// Set up environment variables and logging options
|
||||
|
@ -56,12 +53,12 @@ async fn main() -> KResult<()> {
|
|||
{
|
||||
warn!("This is a demo version, the server will stop in 3 months");
|
||||
let demo = actix_rt::spawn(expiry::demo_timeout());
|
||||
futures::future::select(start_server(server_params, None), demo).await;
|
||||
futures::future::select(Box::pin(start_kms_server(server_params, None)), demo).await;
|
||||
}
|
||||
|
||||
// Start the KMS
|
||||
#[cfg(not(feature = "timeout"))]
|
||||
start_server(server_params, None).await?;
|
||||
Box::pin(start_kms_server(server_params, None)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ use crate::{database::KMSServer, error::KmsError, result::KResult};
|
|||
pub mod access;
|
||||
pub mod google_cse;
|
||||
pub mod kmip;
|
||||
pub mod tee;
|
||||
|
||||
impl actix_web::error::ResponseError for KmsError {
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
|
@ -39,7 +38,6 @@ impl actix_web::error::ResponseError for KmsError {
|
|||
KmsError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
|
||||
|
||||
KmsError::DatabaseError(_)
|
||||
| KmsError::TeeAttestationError(_)
|
||||
| KmsError::ConversionError(_)
|
||||
| KmsError::CryptographicError(_)
|
||||
| KmsError::Redis(_)
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use actix_web::{
|
||||
get,
|
||||
web::{Data, Json},
|
||||
HttpRequest,
|
||||
};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{database::KMSServer, result::KResult, routes::KmsError};
|
||||
|
||||
/// Get the quote of the server running inside a TEE
|
||||
///
|
||||
/// This service is only enabled when the server is running inside a TEE (SEV or SGX)
|
||||
#[cfg(target_os = "linux")]
|
||||
#[get("/tee/attestation_report")]
|
||||
pub async fn get_attestation_report(
|
||||
req: HttpRequest,
|
||||
kms: Data<Arc<KMSServer>>,
|
||||
) -> KResult<Json<String>> {
|
||||
use actix_web::web::Query;
|
||||
use base64::{engine::general_purpose::STANDARD as b64, Engine as _};
|
||||
use cosmian_kms_utils::tee::QuoteParams;
|
||||
|
||||
let params = Query::<QuoteParams>::from_query(req.query_string())?;
|
||||
info!("GET /tee/attestation_report {}", kms.get_user(req)?);
|
||||
Ok(Json(
|
||||
kms.get_attestation_report(
|
||||
b64.decode(¶ms.nonce)
|
||||
.map_err(|_| {
|
||||
KmsError::InvalidRequest(
|
||||
"The nonce should be a valid hexadecimal value".to_string(),
|
||||
)
|
||||
})?
|
||||
.try_into()
|
||||
.map_err(|e| {
|
||||
KmsError::InvalidRequest(format!("The nonce should be 32 bytes long: {e:?}"))
|
||||
})?,
|
||||
)?,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[get("/tee/attestation_report")]
|
||||
pub async fn get_attestation_report(
|
||||
_req: HttpRequest,
|
||||
_kms: Data<Arc<KMSServer>>,
|
||||
) -> KResult<Json<String>> {
|
||||
Err(KmsError::InvalidRequest(
|
||||
"Can't get the attestation report from a non-Linux KMS".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Get the public key of the enclave
|
||||
///
|
||||
/// This service is only enabled when the server is running SGX
|
||||
#[get("/tee/sgx_enclave_public_key")]
|
||||
pub async fn get_enclave_public_key(
|
||||
req: HttpRequest,
|
||||
kms: Data<Arc<KMSServer>>,
|
||||
) -> KResult<Json<String>> {
|
||||
info!("GET /tee/sgx_enclave_public_key {}", kms.get_user(req)?);
|
||||
Ok(Json(kms.get_sgx_enclave_public_key()?))
|
||||
}
|
|
@ -12,7 +12,7 @@ use cosmian_kmip::kmip::{
|
|||
};
|
||||
use cosmian_kms_utils::crypto::curve_25519::{
|
||||
kmip_requests::{ec_create_key_pair_request, get_private_key_request, get_public_key_request},
|
||||
operation::{self, to_curve_25519_256_public_key},
|
||||
operation::{self, to_ec_public_key},
|
||||
};
|
||||
use cosmian_logger::log_utils::log_init;
|
||||
|
||||
|
@ -159,7 +159,7 @@ async fn test_curve_25519_key_pair() -> KResult<()> {
|
|||
// test import of public key
|
||||
let pk_bytes = pk.key_block()?.key_bytes()?;
|
||||
assert_eq!(pk_bytes.len(), X25519_PUBLIC_KEY_LENGTH);
|
||||
let pk = to_curve_25519_256_public_key(&pk_bytes, sk_uid);
|
||||
let pk = to_ec_public_key(&pk_bytes, sk_uid, RecommendedCurve::CURVE25519);
|
||||
let request = Import {
|
||||
unique_identifier: UniqueIdentifier::TextString(String::new()),
|
||||
object_type: ObjectType::PublicKey,
|
||||
|
@ -264,11 +264,21 @@ async fn test_curve_25519_multiple() -> KResult<()> {
|
|||
panic!("not a create key pair response payload");
|
||||
};
|
||||
|
||||
// Should fail in fips mode since ed25519 for ECDH is not allowed.
|
||||
#[cfg(feature = "fips")]
|
||||
assert_eq!(
|
||||
response.items[1].result_status,
|
||||
ResultStatusEnumeration::OperationFailed
|
||||
);
|
||||
#[cfg(not(feature = "fips"))]
|
||||
assert_eq!(
|
||||
response.items[1].result_status,
|
||||
ResultStatusEnumeration::Success
|
||||
);
|
||||
let Some(Operation::CreateKeyPairResponse(_)) = &response.items[1].response_payload else {
|
||||
|
||||
#[cfg(not(feature = "fips"))]
|
||||
let Some(Operation::CreateKeyPairResponse(_)) = &response.items[1].response_payload
|
||||
else {
|
||||
panic!("not a create key pair response payload");
|
||||
};
|
||||
|
||||
|
@ -289,11 +299,21 @@ async fn test_curve_25519_multiple() -> KResult<()> {
|
|||
)
|
||||
);
|
||||
|
||||
// Should fail in fips mode since ed25519 for ECDH is not allowed.
|
||||
#[cfg(feature = "fips")]
|
||||
assert_eq!(
|
||||
response.items[3].result_status,
|
||||
ResultStatusEnumeration::OperationFailed
|
||||
);
|
||||
#[cfg(not(feature = "fips"))]
|
||||
assert_eq!(
|
||||
response.items[3].result_status,
|
||||
ResultStatusEnumeration::Success
|
||||
);
|
||||
let Some(Operation::CreateKeyPairResponse(_)) = &response.items[3].response_payload else {
|
||||
|
||||
#[cfg(not(feature = "fips"))]
|
||||
let Some(Operation::CreateKeyPairResponse(_)) = &response.items[3].response_payload
|
||||
else {
|
||||
panic!("not a create key pair response payload");
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use cosmian_kmip::kmip::{
|
|||
};
|
||||
use cosmian_kms_utils::crypto::curve_25519::{
|
||||
kmip_requests::{ec_create_key_pair_request, get_private_key_request, get_public_key_request},
|
||||
operation::{to_curve_25519_256_public_key, Q_LENGTH_BITS},
|
||||
operation::{to_ec_public_key, Q_LENGTH_BITS},
|
||||
};
|
||||
use cosmian_logger::log_utils::log_init;
|
||||
use tracing::trace;
|
||||
|
@ -153,7 +153,7 @@ async fn test_curve_25519_key_pair() -> KResult<()> {
|
|||
// test import of public key
|
||||
let pk_bytes = pk_key_block.key_bytes()?;
|
||||
assert_eq!(pk_bytes.len(), X25519_PUBLIC_KEY_LENGTH);
|
||||
let pk = to_curve_25519_256_public_key(&pk_bytes, sk_uid);
|
||||
let pk = to_ec_public_key(&pk_bytes, sk_uid, RecommendedCurve::CURVE25519);
|
||||
let request = Import {
|
||||
unique_identifier: UniqueIdentifier::TextString(String::new()),
|
||||
object_type: ObjectType::PublicKey,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue