├── .cargo └── config.toml ├── .github ├── .kodiak.toml └── workflows │ ├── codeql.yaml │ ├── e2e-tests-manual.yaml │ ├── e2e-tests-scheduled.yaml │ ├── packages.yaml │ └── test.yaml ├── .gitignore ├── .gitmodules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── aziotctl ├── Cargo.toml ├── aziotctl-common │ ├── Cargo.toml │ ├── src │ │ ├── check_last_modified.rs │ │ ├── config │ │ │ ├── apply.rs │ │ │ ├── mod.rs │ │ │ └── super_config.rs │ │ ├── host_info.rs │ │ ├── lib.rs │ │ └── system │ │ │ ├── mod.rs │ │ │ ├── restart.rs │ │ │ ├── set_log_level.rs │ │ │ ├── status.rs │ │ │ ├── stop.rs │ │ │ └── system_logs.rs │ └── test-files │ │ └── apply │ │ ├── README.md │ │ ├── dps-symmetric-key-no-pad │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-symmetric-key │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-tpm │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-est-bootstrap-auto-renew │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11-est-bootstrap │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11-est-custom-bootstrap │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11-est-subject-dn-bootstrap │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11-est │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11-localca │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509-pkcs11 │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── dps-x509 │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── local-gateway │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-connection-string │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-symmetric-key-no-pad │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-symmetric-key │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-x509-est-custom-http │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-x509-est-custom │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-x509-est-subject-dn │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-x509-pkcs11 │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ ├── manual-x509 │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml │ │ └── throttle-limits │ │ ├── certd.toml │ │ ├── config.toml │ │ ├── device-id │ │ ├── identityd.toml │ │ ├── keyd.toml │ │ └── tpmd.toml ├── config │ └── unix │ │ └── template.toml └── src │ ├── check.rs │ ├── check_list.rs │ ├── config │ ├── apply.rs │ ├── mod.rs │ └── mp.rs │ ├── internal │ ├── check │ │ ├── additional_info.rs │ │ ├── checks │ │ │ ├── aziot_version.rs │ │ │ ├── cert_expiry.rs │ │ │ ├── certs_match_private_keys.rs │ │ │ ├── certs_preloaded.rs │ │ │ ├── daemons_running.rs │ │ │ ├── est_server_https.rs │ │ │ ├── host_connect_dps_endpoint.rs │ │ │ ├── host_connect_iothub.rs │ │ │ ├── host_local_time.rs │ │ │ ├── hostname.rs │ │ │ ├── mod.rs │ │ │ ├── read_certs.rs │ │ │ ├── read_key_pairs.rs │ │ │ ├── up_to_date_configs.rs │ │ │ └── well_formed_configs.rs │ │ ├── mod.rs │ │ └── util.rs │ ├── common.rs │ └── mod.rs │ ├── main.rs │ └── system.rs ├── aziotd ├── Cargo.toml └── src │ ├── error.rs │ └── main.rs ├── cert ├── aziot-cert-client-async │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-cert-common-http │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-cert-common │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-certd-config │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── util.rs ├── aziot-certd │ ├── Cargo.toml │ ├── aziot-certd.service.in │ ├── aziot-certd.socket.in │ ├── config │ │ └── unix │ │ │ └── default.toml │ ├── openapi │ │ └── 2020-09-01.yaml │ └── src │ │ ├── error.rs │ │ ├── est.rs │ │ ├── http │ │ ├── create.rs │ │ ├── get_or_import_or_delete.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ └── renewal.rs └── cert-renewal │ ├── Cargo.toml │ └── src │ ├── cert_interface.rs │ ├── credential.rs │ ├── engine.rs │ ├── error.rs │ ├── lib.rs │ ├── policy.rs │ └── time.rs ├── ci ├── code-coverage.sh ├── e2e-tests │ ├── DpsCustomAllocation.csfunc │ ├── az-login.sh │ ├── helper-functions.sh │ ├── suite-cleanup.sh │ ├── suite-common.sh │ ├── suite-setup.sh │ ├── test-cleanup.sh │ ├── test-common.sh │ └── test-run.sh ├── install-build-deps.sh ├── install-runtime-deps.sh ├── install-test-deps.sh ├── iothub-get-twin.sh ├── mock-iot-tests │ ├── mock-iot-cert-gen.sh │ ├── mock-iot-provision.sh │ └── mock-iot-setup.sh ├── package.sh ├── test-aziot-key-openssl-engine-shared.sh └── test-basic.sh ├── config-common ├── Cargo.toml └── src │ ├── error.rs │ ├── lib.rs │ └── watcher.rs ├── contrib ├── debian │ ├── changelog │ ├── compat │ ├── control │ ├── copyright │ ├── postinst │ ├── postrm │ ├── preinst │ ├── rules │ └── source │ │ └── format ├── enterprise-linux │ ├── 00-aziot.preset │ └── aziot-identity-service.spec.in ├── mariner │ ├── aziot-identity-service.signatures.json │ └── aziot-identity-service.spec.in ├── snap │ └── command-chain │ │ └── launch-wrapper.sh └── third-party-notices.sh ├── docs-dev ├── Makefile ├── README.md ├── building.md ├── e2e-tests.md ├── est-ca.md ├── img │ ├── device-init-est-ca-online.svg │ ├── device-init-local-ca-offline.svg │ ├── est-ca-cloud-setup.svg │ ├── est-ca-device-setup.svg │ ├── est-ca-provisioning-detailed.svg │ ├── est-ca-provisioning-simple.svg │ ├── est-ca-runtime-operation-detailed.svg │ ├── est-ca-runtime-operation-simple.svg │ ├── new-component-overview-detailed.svg │ ├── new-component-overview-simple.svg │ ├── old-component-overview.svg │ ├── openssl-engine-internals-tls-client.svg │ └── operation-mr-deviceca.svg ├── openssl-engine-internals.md ├── packages.md ├── packaging.md ├── plantuml │ ├── device-init-est-ca-online.plantuml │ ├── device-init-local-ca-offline.plantuml │ ├── est-ca-cloud-setup.plantuml │ ├── est-ca-device-setup.plantuml │ ├── est-ca-provisioning-detailed.plantuml │ ├── est-ca-provisioning-simple.plantuml │ ├── est-ca-runtime-operation-detailed.plantuml │ ├── est-ca-runtime-operation-simple.plantuml │ ├── new-component-overview-detailed.plantuml │ ├── new-component-overview-simple.plantuml │ ├── old-component-overview.plantuml │ ├── openssl-engine-internals-tls-client.plantuml │ ├── operation-hostmodule-sas-seqeuence.plantuml │ └── operation-mr-deviceca.plantuml ├── running │ ├── aziot-certd.md │ ├── aziot-identityd.md │ ├── aziot-keyd.md │ ├── aziot-tpmd.md │ ├── index.md │ ├── pkcs11.md │ └── swtpm.md └── tpm-service.md ├── docs ├── _config.yml ├── _includes │ ├── anchor_headings.html │ └── nav.html ├── _layouts │ └── default.html ├── api │ ├── certificates-service.md │ ├── identity-service.md │ ├── index.md │ └── keys-service.md ├── aziotctl.md ├── configuration.md ├── develop-an-agent.md ├── img │ └── operation-hostmodule-sas-sequence.svg ├── index.md ├── installation.md ├── pkcs11 │ ├── cryptoauthlib.md │ ├── index.md │ ├── softhsm.md │ └── tpm2-pkcs11.md ├── socket-throttling.md └── using-est-with-certd.md ├── http-common ├── Cargo.toml └── src │ ├── backoff.rs │ ├── connector.rs │ ├── dynrange.rs │ ├── lib.rs │ ├── proxy.rs │ ├── request.rs │ ├── server.rs │ └── uid.rs ├── identity ├── aziot-cloud-client-async │ ├── Cargo.toml │ └── src │ │ ├── connector.rs │ │ ├── dps │ │ ├── mod.rs │ │ └── schema.rs │ │ ├── hub │ │ └── mod.rs │ │ └── lib.rs ├── aziot-identity-client-async │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-identity-common-http │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-identity-common │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-identityd-config │ ├── Cargo.toml │ ├── src │ │ ├── check.rs │ │ └── lib.rs │ └── test │ │ ├── complex_payload.json │ │ ├── good_dps_config.toml │ │ ├── good_dps_config_with_complex_payload.toml │ │ ├── good_dps_config_with_simple_payload.toml │ │ ├── good_sas_config.toml │ │ └── simple_payload.json ├── aziot-identityd │ ├── Cargo.toml │ ├── aziot-identityd.service.in │ ├── aziot-identityd.socket.in │ ├── build.rs │ ├── config │ │ └── unix │ │ │ └── default.toml │ ├── openapi │ │ ├── 2020-09-01-preview.yaml │ │ ├── 2020-09-01.yaml │ │ ├── 2021-12-01.yaml │ │ └── 2022-08-01.yaml │ ├── src │ │ ├── auth │ │ │ ├── authentication.rs │ │ │ ├── authorization.rs │ │ │ └── mod.rs │ │ ├── configext.rs │ │ ├── error.rs │ │ ├── http │ │ │ ├── create_or_list_module_identity.rs │ │ │ ├── get_caller_identity.rs │ │ │ ├── get_device_identity.rs │ │ │ ├── get_provisioning_info.rs │ │ │ ├── get_trust_bundle.rs │ │ │ ├── get_update_or_delete_module_identity.rs │ │ │ ├── mod.rs │ │ │ └── reprovision_device.rs │ │ ├── identity.rs │ │ ├── lib.rs │ │ └── renewal.rs │ └── test │ │ ├── bad_config.toml │ │ ├── bad_local_config.toml │ │ ├── good_auth_settings.toml │ │ └── good_local_opts.toml └── mock-iot-server │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── dps.rs │ ├── hub.rs │ ├── main.rs │ └── server.rs ├── key ├── aziot-key-client-async │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-key-client │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-key-common-http │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-key-common │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-key-openssl-engine-shared-test │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── aziot-key-openssl-engine-shared │ ├── Cargo.toml │ ├── build │ │ ├── engine.c │ │ └── main.rs │ └── src │ │ └── lib.rs ├── aziot-key-openssl-engine │ ├── Cargo.toml │ ├── build │ │ ├── engine.c │ │ └── main.rs │ └── src │ │ ├── ec_key.rs │ │ ├── engine.rs │ │ ├── ex_data.rs │ │ ├── lib.rs │ │ └── rsa.rs ├── aziot-keyd-config │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-keyd │ ├── Cargo.toml │ ├── aziot-keyd.service.in │ ├── aziot-keyd.socket.in │ ├── build.rs │ ├── config │ │ └── unix │ │ │ └── default.toml │ ├── openapi │ │ ├── 2020-09-01.yaml │ │ └── 2021-05-01.yaml │ └── src │ │ ├── error.rs │ │ ├── http │ │ ├── create_delete_key.rs │ │ ├── create_delete_key_pair.rs │ │ ├── create_derived_key.rs │ │ ├── decrypt.rs │ │ ├── encrypt.rs │ │ ├── export_derived_key.rs │ │ ├── get_key_pair_public_parameter.rs │ │ ├── load_move.rs │ │ ├── mod.rs │ │ └── sign.rs │ │ ├── keys.rs │ │ └── lib.rs ├── aziot-keys-common │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── aziot-keys │ ├── Cargo.toml │ ├── aziot-keys.h │ ├── cbindgen.prelude.h │ ├── cbindgen.toml │ └── src │ │ ├── function_list │ │ ├── mod.rs │ │ ├── v2_0_0_0.rs │ │ └── v2_1_0_0.rs │ │ ├── implementation.rs │ │ ├── key.rs │ │ ├── key_pair.rs │ │ └── lib.rs └── test-aziot-key-openssl-engine-shared.sh ├── logger ├── Cargo.toml └── src │ └── lib.rs ├── mini-sntp ├── Cargo.toml └── src │ ├── error.rs │ └── lib.rs ├── openssl-build ├── Cargo.toml └── src │ └── lib.rs ├── openssl-sys2 ├── Cargo.toml ├── build │ ├── compat.c │ └── main.rs └── src │ ├── asn1.rs │ ├── ec.rs │ ├── ecdsa.rs │ ├── engine.rs │ ├── evp.rs │ ├── lib.rs │ ├── rsa.rs │ └── x509.rs ├── openssl2 ├── Cargo.toml ├── build │ └── main.rs └── src │ ├── extension.rs │ └── lib.rs ├── pkcs11 ├── pkcs11-sys │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── pkcs11 │ ├── Cargo.toml │ ├── build.rs │ └── src │ ├── context.rs │ ├── dl.rs │ ├── lib.rs │ ├── object.rs │ └── session.rs ├── rust-toolchain.toml ├── snap ├── hooks │ ├── configure │ └── install └── snapcraft.yaml ├── test-common ├── Cargo.toml └── src │ ├── client │ ├── cert.rs │ ├── identity.rs │ ├── key.rs │ └── mod.rs │ ├── credential.rs │ ├── lib.rs │ └── tokio_openssl2.rs ├── third-party ├── cgmanifest.json └── generate_cgmanifest.sh └── tpm ├── aziot-tpm-client-async ├── Cargo.toml └── src │ └── lib.rs ├── aziot-tpm-common-http ├── Cargo.toml └── src │ └── lib.rs ├── aziot-tpm-common ├── Cargo.toml └── src │ └── lib.rs ├── aziot-tpmd-config ├── Cargo.toml └── src │ └── lib.rs ├── aziot-tpmd ├── Cargo.toml ├── aziot-tpmd.service.in ├── aziot-tpmd.socket.in ├── config │ └── unix │ │ └── default.toml └── src │ ├── error.rs │ ├── http │ ├── get_tpm_keys.rs │ ├── import_auth_key.rs │ ├── mod.rs │ └── sign_with_auth_key.rs │ └── lib.rs └── tss-minimal ├── Cargo.toml ├── esys-sys ├── Cargo.toml ├── build.rs ├── src │ └── lib.rs └── wrapper.h ├── mu-sys ├── Cargo.toml ├── build.rs ├── src │ └── lib.rs └── wrapper.h ├── rc-sys ├── Cargo.toml ├── build.rs ├── src │ └── lib.rs └── wrapper.h ├── src ├── error.rs ├── handle.rs ├── lib.rs ├── marshal.rs └── types.rs ├── tcti-sys ├── Cargo.toml ├── build.rs ├── src │ └── lib.rs └── wrapper.h ├── tests ├── create_primary.rs ├── evict_control.rs ├── from_tpm_public.rs └── policy_secret.rs └── types-sys ├── Cargo.toml ├── build.rs ├── const_define.sh ├── src └── lib.rs └── wrapper.h.in /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | USER_AZIOTID = "aziotid" 3 | USER_AZIOTKS = "aziotks" 4 | USER_AZIOTCS = "aziotcs" 5 | USER_AZIOTTPM = "aziottpm" 6 | SOCKET_DIR = "/run/aziot" 7 | 8 | [registries] 9 | iotedge_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/iotedge/iotedge/_packaging/iotedge_PublicPackages/Cargo/index/" } 10 | 11 | [registry] 12 | global-credential-providers = ["cargo:token", "cargo:libsecret"] 13 | 14 | [source.crates-io] 15 | replace-with = "iotedge_PublicPackages" 16 | -------------------------------------------------------------------------------- /.github/.kodiak.toml: -------------------------------------------------------------------------------- 1 | # https://kodiakhq.com/docs/config-reference contains all parameters explained 2 | version = 1 3 | 4 | [update] 5 | # Update a PR whenever out of date with the base branch. The PR will be updated regardless of 6 | # merge requirements (e.g. failing status checks, missing reviews). 7 | always = false # default: false 8 | 9 | # When enabled, Kodiak will only update PRs that have an automerge label. When disabled, any PR. 10 | require_automerge_label = true # default: true 11 | 12 | [merge] 13 | # Merge method for Kodiak to use. 14 | method = "squash" # default: "merge" 15 | 16 | # Once a PR is merged, delete the branch. 17 | delete_branch_on_merge = true # default: false 18 | 19 | # When enabled, Kodiak will only update PRs that have an automerge label. 20 | # When disabled, automatically merge any PR that passes all required checks. 21 | require_automerge_label = true # default: true 22 | 23 | # By default, Kodiak will only act on PRs that have this label. 24 | automerge_label = "ready-to-merge" # default: "automerge" 25 | 26 | [merge.message] 27 | # use title of PR for merge commit. 28 | title = "pull_request_title" # default: "github_default" 29 | 30 | # use body of PR for merge commit. 31 | body = "pull_request_body" # default: "github_default" 32 | 33 | # Add the pull request author as a coauthor of the merge commit using 34 | include_pull_request_author = false # default: false 35 | 36 | # remove html comments to auto remove PR templates. 37 | strip_html_comments = true # default: false 38 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yaml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main", "release/1.*" ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ "main", "release/1.*" ] 9 | schedule: 10 | - cron: '34 19 * * 4' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: 'ubuntu-22.04' 16 | timeout-minutes: 360 17 | permissions: 18 | actions: read 19 | contents: read 20 | security-events: write 21 | 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | language: [ 'cpp' ] 26 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] 27 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 28 | 29 | steps: 30 | - name: Checkout repository 31 | uses: actions/checkout@v3 32 | 33 | # Initializes the CodeQL tools for scanning. 34 | - name: Initialize CodeQL 35 | uses: github/codeql-action/init@v2 36 | with: 37 | languages: ${{ matrix.language }} 38 | 39 | - name: 'Build' 40 | run: | 41 | sudo apt-get update 42 | sudo apt-get install -y libtss2-dev 43 | DISABLE_FOR_CODEQL=1 . ci/install-build-deps.sh 44 | rm -r third-party/tpm2-tss 45 | make 46 | 47 | - name: Perform CodeQL Analysis 48 | uses: github/codeql-action/analyze@v2 49 | with: 50 | category: "/language:${{matrix.language}}" 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /key/aziot-keyd/src/keys.generated.rs 2 | /packages 3 | /target 4 | .vscode 5 | 6 | /parts 7 | /stage 8 | /prime 9 | *.snap 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/libtpms"] 2 | path = third-party/libtpms 3 | url = https://github.com/stefanberger/libtpms.git 4 | [submodule "third-party/swtpm"] 5 | path = third-party/swtpm 6 | url = https://github.com/stefanberger/swtpm.git 7 | [submodule "third-party/tpm2-tss"] 8 | path = third-party/tpm2-tss 9 | url = https://github.com/tpm2-software/tpm2-tss.git 10 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "aziotctl", 4 | "aziotctl/aziotctl-common", 5 | 6 | "aziotd", 7 | 8 | "cert/aziot-cert-client-async", 9 | "cert/aziot-cert-common", 10 | "cert/aziot-cert-common-http", 11 | "cert/aziot-certd-config", 12 | "cert/aziot-certd", 13 | "cert/cert-renewal", 14 | 15 | "config-common", 16 | 17 | "http-common", 18 | 19 | "identity/aziot-cloud-client-async", 20 | "identity/aziot-identity-client-async", 21 | "identity/aziot-identity-common", 22 | "identity/aziot-identity-common-http", 23 | "identity/aziot-identityd-config", 24 | "identity/aziot-identityd", 25 | "identity/mock-iot-server", 26 | 27 | "key/aziot-key-client", 28 | "key/aziot-key-client-async", 29 | "key/aziot-key-common", 30 | "key/aziot-key-common-http", 31 | "key/aziot-keyd-config", 32 | "key/aziot-keyd", 33 | "key/aziot-key-openssl-engine", 34 | "key/aziot-key-openssl-engine-shared", 35 | "key/aziot-key-openssl-engine-shared-test", 36 | "key/aziot-keys", 37 | "key/aziot-keys-common", 38 | 39 | "logger", 40 | 41 | "mini-sntp", 42 | 43 | "openssl2", 44 | "openssl-build", 45 | "openssl-sys2", 46 | 47 | "pkcs11/pkcs11", 48 | "pkcs11/pkcs11-sys", 49 | 50 | "test-common", 51 | 52 | "tpm/aziot-tpm-client-async", 53 | "tpm/aziot-tpm-common-http", 54 | "tpm/aziot-tpm-common", 55 | "tpm/aziot-tpmd-config", 56 | "tpm/aziot-tpmd", 57 | "tpm/tss-minimal", 58 | ] 59 | resolver = "2" 60 | 61 | # Don't let panics from callbacks cross FFI boundary 62 | 63 | [profile.dev] 64 | panic = "abort" 65 | 66 | [profile.release] 67 | panic = "abort" 68 | # Release builds will have full symbols. The packaging phase will strip symbols from binaries and 69 | # make them available in a separate package. 70 | # Notes: Snaps don't have a good story for debug symbols, so for now we'll override this setting in 71 | # the snapcraft.yaml file by setting CARGO_PROFILE_RELEASE_DEBUG=0. 72 | debug = 2 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains the code of the Azure IoT Identity Service and related services. Together these services make a basic device "runtime" for Azure IoT devices. 2 | 3 | 4 | # Documentation 5 | 6 | The contents of the `docs/` directory are served at 7 | 8 | See [`docs-dev/README.md`](docs-dev/README.md) for developer documentation, and [`CONTRIBUTING`](CONTRIBUTING.md) for contribution guidelines. 9 | 10 | 11 | # License 12 | 13 | MIT 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziotctl-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | anyhow = "1" 10 | base64 = "0.21" 11 | log = "0.4" 12 | nix = "0.26" 13 | serde = { version = "1", features = ["derive"] } 14 | serde_json = "1" 15 | serde_with = "2" 16 | url = { version = "2", features = ["serde"] } 17 | 18 | aziot-certd-config = { path = "../../cert/aziot-certd-config" } 19 | aziot-identityd-config = { path = "../../identity/aziot-identityd-config" } 20 | aziot-keyd-config = { path = "../../key/aziot-keyd-config" } 21 | aziot-keys-common = { path = "../../key/aziot-keys-common", features = ["serde"] } 22 | aziot-tpmd-config = { path = "../../tpm/aziot-tpmd-config" } 23 | cert-renewal = { path = "../../cert/cert-renewal" } 24 | http-common = { path = "../../http-common" } 25 | 26 | [dev-dependencies] 27 | bytes = "1" 28 | toml = "0.7" 29 | 30 | [features] 31 | snapctl = [] 32 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/src/system/stop.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use std::process::Command; 4 | 5 | use anyhow::{Context, Result}; 6 | 7 | use super::{print_command_error, ServiceDefinition}; 8 | 9 | #[cfg(not(feature = "snapctl"))] 10 | pub fn stop(services: &[&ServiceDefinition]) -> Result<()> { 11 | // stop all services 12 | for service in services.iter().map(|s| s.service) { 13 | print!("Stopping {service}..."); 14 | let result = Command::new("systemctl") 15 | .args(["stop", service]) 16 | .output() 17 | .context("Failed to call systemctl stop")?; 18 | 19 | if result.status.success() { 20 | println!("Stopped!"); 21 | } else { 22 | print_command_error(&result); 23 | } 24 | } 25 | 26 | Ok(()) 27 | } 28 | 29 | #[cfg(feature = "snapctl")] 30 | pub fn stop(services: &[&ServiceDefinition]) -> Result<()> { 31 | let snap_instance_name = match std::env::var("SNAP_INSTANCE_NAME") { 32 | Ok(snap_instance_name) => snap_instance_name, 33 | Err(_) => { 34 | std::env::var("SNAP_NAME").expect("snapctl must be used within the context of a snap") 35 | } 36 | }; 37 | 38 | print!("Stopping {} services...", snap_instance_name); 39 | 40 | let service_names = services.iter().map(|s| { 41 | s.service 42 | .trim_start_matches("snap.") 43 | .trim_end_matches(".service") 44 | }); 45 | 46 | let result = Command::new("snapctl") 47 | .arg("stop") 48 | .args(service_names) 49 | .output() 50 | .context("Failed to call snapctl stop")?; 51 | 52 | if result.status.success() { 53 | println!("Stopped!"); 54 | } else { 55 | print_command_error(&result); 56 | } 57 | 58 | Ok(()) 59 | } 60 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/src/system/system_logs.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use std::ffi::OsStr; 4 | use std::process::Command; 5 | 6 | use anyhow::{Context, Result}; 7 | 8 | pub fn get_system_logs(processes: &[&str], additional_args: &[&OsStr]) -> Result<()> { 9 | let processes = processes.iter().flat_map(|p| vec!["-u", p]); 10 | let default_args = [OsStr::new("-e"), OsStr::new("--no-pager")]; 11 | 12 | // NOTE: Clippy is incorrectly suggesting to remove the borrow on 13 | // default_args. 14 | #[allow(clippy::needless_borrow)] 15 | Command::new("journalctl") 16 | .args(processes) 17 | .args(if additional_args.is_empty() { 18 | &default_args 19 | } else { 20 | additional_args 21 | }) 22 | .spawn() 23 | .context("Failed to spawn new process for getting logs")? 24 | .wait() 25 | .context("Failed to call journalctl")?; 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/README.md: -------------------------------------------------------------------------------- 1 | This directory contains test files for the `aziotctl config apply` tests. 2 | 3 | For each test, passing `input.txt` to `aziotctl config apply` should produce the four services' configs in `keyd.toml`, `certd.toml`, `identityd.toml` and `tpmd.toml`. In the tests that involve a symmetric key, the `device-id` file stores the contents of the `/var/secrets/aziot/keyd/device-id` file that `aziotctl config apply` would generate. 4 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "symmetric_key" 8 | registration_id = "my-device" 9 | symmetric_key = { value = "YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGVudGl0eS1zZXJ2aWNlfGF6aW90LWlkZW50aXR5LXNlcg" } 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-identity-service|aziot-identity-ser -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "symmetric_key" 12 | registration_id = "my-device" 13 | symmetric_key = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key-no-pad/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "symmetric_key" 8 | registration_id = "my-device" 9 | symmetric_key = { value = "YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGVudGl0eS1zZXJ2aWNlfGF6aW90LWlkZW50aXR5LXNlcg==" } 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-identity-service|aziot-identity-ser -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "symmetric_key" 12 | registration_id = "my-device" 13 | symmetric_key = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-symmetric-key/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-tpm/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-tpm/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "tpm" 8 | registration_id = "my-device" 9 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-tpm/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "tpm" 12 | registration_id = "my-device" 13 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-tpm/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | 6 | [[principal]] 7 | uid = 5556 8 | keys = ["aziot_identityd_master_id"] 9 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-tpm/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-tpm/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.est] 4 | trusted_certs = ["est-server-ca-1"] 5 | 6 | [cert_issuance.device-id] 7 | method = "est" 8 | url = "https://example.org/.well-known/est" 9 | identity_cert = "est-id-device-id" 10 | identity_pk = "est-id-device-id" 11 | bootstrap_identity_cert = "est-bootstrap-id-device-id" 12 | bootstrap_identity_pk = "est-bootstrap-id-device-id" 13 | 14 | [cert_issuance.device-id.subject] 15 | CN = "my-device" 16 | L = "AQ" 17 | ST = "Antarctica" 18 | 19 | [cert_issuance.device-id-temp] 20 | method = "est" 21 | url = "https://example.org/.well-known/est" 22 | identity_cert = "est-id-device-id" 23 | identity_pk = "est-id-device-id" 24 | bootstrap_identity_cert = "est-bootstrap-id-device-id" 25 | bootstrap_identity_pk = "est-bootstrap-id-device-id" 26 | 27 | [cert_issuance.device-id-temp.subject] 28 | CN = "my-device" 29 | L = "AQ" 30 | ST = "Antarctica" 31 | 32 | [preloaded_certs] 33 | est-bootstrap-id-device-id = "file:///var/secrets/est-bootstrap-id.pem" 34 | est-server-ca-1 = "file:///var/secrets/est-id-ca.pem" 35 | 36 | [[principal]] 37 | uid = 5556 38 | certs = ["device-id-temp", "device-id"] 39 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | 10 | [provisioning.attestation.identity_cert] 11 | method = "est" 12 | url = "https://example.org/.well-known/est" 13 | bootstrap_identity_cert = "file:///var/secrets/est-bootstrap-id.pem" 14 | bootstrap_identity_pk = "file:///var/secrets/est-bootstrap-id-key.pem" 15 | 16 | [provisioning.attestation.identity_cert.subject] 17 | L = "AQ" 18 | ST = "Antarctica" 19 | CN = "my-device" 20 | 21 | [provisioning.attestation.identity_cert.auto_renew] 22 | rotate_key = false 23 | threshold = "50%" 24 | retry = "10%" 25 | 26 | [cert_issuance.est] 27 | trusted_certs = [ 28 | "file:///var/secrets/est-id-ca.pem", 29 | ] 30 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | 15 | [provisioning.attestation.registration_id] 16 | CN = "my-device" 17 | L = "AQ" 18 | ST = "Antarctica" 19 | 20 | [provisioning.attestation.identity_auto_renew] 21 | rotate_key = false 22 | threshold = "50%" 23 | retry = "10%" 24 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | est-bootstrap-id-device-id = "file:///var/secrets/est-bootstrap-id-key.pem" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | 11 | [[principal]] 12 | uid = 5555 13 | keys = ["est-bootstrap-id-device-id", "est-id-device-id-temp", "est-id-device-id"] 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-est-bootstrap-auto-renew/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.est] 4 | trusted_certs = ["est-server-ca-1"] 5 | username = "estuser" 6 | password = "estpwd" 7 | identity_cert = "est-id" 8 | identity_pk = "est-id" 9 | bootstrap_identity_cert = "est-bootstrap-id" 10 | bootstrap_identity_pk = "est-bootstrap-id" 11 | 12 | [cert_issuance.est.identity_auto_renew] 13 | rotate_key = true 14 | threshold = "50%" 15 | retry = "10%" 16 | 17 | [cert_issuance.est.urls] 18 | default = "https://example.org/.well-known/est" 19 | 20 | [cert_issuance.device-id] 21 | method = "est" 22 | common_name = "my-device" 23 | 24 | [cert_issuance.device-id-temp] 25 | method = "est" 26 | common_name = "my-device" 27 | 28 | [preloaded_certs] 29 | est-bootstrap-id = "file:///var/secrets/est-bootstrap-id.pem" 30 | est-server-ca-1 = "file:///var/secrets/est-id-ca.pem" 31 | 32 | [[principal]] 33 | uid = 5556 34 | certs = ["device-id-temp", "device-id"] 35 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | 10 | [provisioning.attestation.identity_cert] 11 | method = "est" 12 | common_name = "my-device" 13 | 14 | [provisioning.attestation.identity_cert.auto_renew] 15 | rotate_key = true 16 | threshold = "90%" 17 | retry = "1%" 18 | 19 | [aziot_keys] 20 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 21 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 22 | 23 | [cert_issuance.est] 24 | trusted_certs = [ 25 | "file:///var/secrets/est-id-ca.pem", 26 | ] 27 | 28 | [cert_issuance.est.auth] 29 | username = "estuser" 30 | password = "estpwd" 31 | bootstrap_identity_cert = "file:///var/secrets/est-bootstrap-id.pem" 32 | bootstrap_identity_pk = "pkcs11:slot-id=0;object=est-bootstrap-id?pin-value=1234" 33 | 34 | [cert_issuance.est.identity_auto_renew] 35 | rotate_key = true 36 | threshold = "50%" 37 | retry = "10%" 38 | 39 | [cert_issuance.est.urls] 40 | default = "https://example.org/.well-known/est" 41 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | 16 | [provisioning.attestation.identity_auto_renew] 17 | rotate_key = true 18 | threshold = "90%" 19 | retry = "1%" 20 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | est-bootstrap-id = "pkcs11:slot-id=0;object=est%2Dbootstrap%2Did?pin-value=1234" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id", "device-id-temp"] 12 | 13 | [[principal]] 14 | uid = 5555 15 | keys = ["est-bootstrap-id", "est-id", "est-id-temp"] 16 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-bootstrap/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.est] 4 | trusted_certs = ["est-server-ca-1"] 5 | username = "estuser" 6 | password = "estpwd" 7 | identity_cert = "est-id" 8 | identity_pk = "est-id" 9 | bootstrap_identity_cert = "est-bootstrap-id" 10 | bootstrap_identity_pk = "est-bootstrap-id" 11 | 12 | [cert_issuance.est.urls] 13 | default = "https://example.org/.well-known/est" 14 | 15 | [cert_issuance.device-id] 16 | method = "est" 17 | url = "https://example.org/.well-known/custom/est" 18 | identity_cert = "est-id-device-id" 19 | identity_pk = "est-id-device-id" 20 | bootstrap_identity_cert = "est-bootstrap-id-device-id" 21 | bootstrap_identity_pk = "est-bootstrap-id-device-id" 22 | common_name = "my-device" 23 | 24 | [preloaded_certs] 25 | est-bootstrap-id = "file:///var/secrets/est-bootstrap-id.pem" 26 | est-bootstrap-id-device-id = "file:///var/secrets/est-custom-bootstrap-id.pem" 27 | est-server-ca-1 = "file:///var/secrets/est-id-ca.pem" 28 | 29 | [[principal]] 30 | uid = 5556 31 | certs = ["device-id"] 32 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | 10 | [provisioning.attestation.identity_cert] 11 | method = "est" 12 | common_name = "my-device" 13 | url = "https://example.org/.well-known/custom/est" 14 | bootstrap_identity_cert = "file:///var/secrets/est-custom-bootstrap-id.pem" 15 | bootstrap_identity_pk = "pkcs11:slot-id=0;object=est-custom-bootstrap-id?pin-value=1234" 16 | 17 | [aziot_keys] 18 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 19 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 20 | 21 | [cert_issuance.est] 22 | trusted_certs = [ 23 | "file:///var/secrets/est-id-ca.pem", 24 | ] 25 | 26 | [cert_issuance.est.auth] 27 | username = "estuser" 28 | password = "estpwd" 29 | bootstrap_identity_cert = "file:///var/secrets/est-bootstrap-id.pem" 30 | bootstrap_identity_pk = "pkcs11:slot-id=0;object=est-bootstrap-id?pin-value=1234" 31 | 32 | [cert_issuance.est.urls] 33 | default = "https://example.org/.well-known/est" 34 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | est-bootstrap-id = "pkcs11:slot-id=0;object=est%2Dbootstrap%2Did?pin-value=1234" 8 | est-bootstrap-id-device-id = "pkcs11:slot-id=0;object=est%2Dcustom%2Dbootstrap%2Did?pin-value=1234" 9 | 10 | [[principal]] 11 | uid = 5556 12 | keys = ["aziot_identityd_master_id", "device-id"] 13 | 14 | [[principal]] 15 | uid = 5555 16 | keys = ["est-bootstrap-id-device-id", "est-id-device-id-temp", "est-id-device-id", "est-bootstrap-id", "est-id", "est-id-temp"] 17 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-custom-bootstrap/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.est] 4 | trusted_certs = ["est-server-ca-1"] 5 | username = "estuser" 6 | password = "estpwd" 7 | identity_cert = "est-id" 8 | identity_pk = "est-id" 9 | bootstrap_identity_cert = "est-bootstrap-id" 10 | bootstrap_identity_pk = "est-bootstrap-id" 11 | 12 | [cert_issuance.est.urls] 13 | default = "https://example.org/.well-known/est" 14 | 15 | [cert_issuance.device-id] 16 | method = "est" 17 | url = "https://example.org/.well-known/custom/est" 18 | identity_cert = "est-id-device-id" 19 | identity_pk = "est-id-device-id" 20 | bootstrap_identity_cert = "est-bootstrap-id-device-id" 21 | bootstrap_identity_pk = "est-bootstrap-id-device-id" 22 | 23 | [cert_issuance.device-id.subject] 24 | CN = "my-device" 25 | L = "AQ" 26 | ST = "Antarctica" 27 | 28 | [preloaded_certs] 29 | est-bootstrap-id = "file:///var/secrets/est-bootstrap-id.pem" 30 | est-bootstrap-id-device-id = "file:///var/secrets/est-custom-bootstrap-id.pem" 31 | est-server-ca-1 = "file:///var/secrets/est-id-ca.pem" 32 | 33 | [[principal]] 34 | uid = 5556 35 | certs = ["device-id"] 36 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | 10 | [provisioning.attestation.identity_cert] 11 | method = "est" 12 | url = "https://example.org/.well-known/custom/est" 13 | bootstrap_identity_cert = "file:///var/secrets/est-custom-bootstrap-id.pem" 14 | bootstrap_identity_pk = "pkcs11:slot-id=0;object=est-custom-bootstrap-id?pin-value=1234" 15 | subject = { L = "AQ", ST = "Antarctica", CN = "my-device" } 16 | 17 | [aziot_keys] 18 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 19 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 20 | 21 | [cert_issuance.est] 22 | trusted_certs = [ 23 | "file:///var/secrets/est-id-ca.pem", 24 | ] 25 | 26 | [cert_issuance.est.auth] 27 | username = "estuser" 28 | password = "estpwd" 29 | bootstrap_identity_cert = "file:///var/secrets/est-bootstrap-id.pem" 30 | bootstrap_identity_pk = "pkcs11:slot-id=0;object=est-bootstrap-id?pin-value=1234" 31 | 32 | [cert_issuance.est.urls] 33 | default = "https://example.org/.well-known/est" 34 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | 15 | [provisioning.attestation.registration_id] 16 | CN = "my-device" 17 | L = "AQ" 18 | ST = "Antarctica" 19 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | est-bootstrap-id = "pkcs11:slot-id=0;object=est%2Dbootstrap%2Did?pin-value=1234" 8 | est-bootstrap-id-device-id = "pkcs11:slot-id=0;object=est%2Dcustom%2Dbootstrap%2Did?pin-value=1234" 9 | 10 | [[principal]] 11 | uid = 5556 12 | keys = ["aziot_identityd_master_id", "device-id"] 13 | 14 | [[principal]] 15 | uid = 5555 16 | keys = ["est-bootstrap-id-device-id", "est-id-device-id-temp", "est-id-device-id", "est-bootstrap-id", "est-id", "est-id-temp"] 17 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est-subject-dn-bootstrap/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.est] 4 | trusted_certs = ["est-server-ca-1"] 5 | username = "estuser" 6 | password = "estpwd" 7 | identity_cert = "est-id" 8 | identity_pk = "est-id" 9 | 10 | [cert_issuance.est.urls] 11 | default = "https://example.org/.well-known/est" 12 | 13 | [cert_issuance.device-id] 14 | method = "est" 15 | common_name = "my-device" 16 | 17 | [preloaded_certs] 18 | est-id = "file:///var/secrets/est-id.pem" 19 | est-server-ca-1 = "file:///var/secrets/est-id-ca.pem" 20 | 21 | [[principal]] 22 | uid = 5556 23 | certs = ["device-id"] 24 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | identity_cert = { method = "est", common_name = "my-device" } 10 | 11 | [aziot_keys] 12 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 13 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 14 | 15 | [cert_issuance.est] 16 | trusted_certs = [ 17 | "file:///var/secrets/est-id-ca.pem", 18 | ] 19 | 20 | [cert_issuance.est.auth] 21 | username = "estuser" 22 | password = "estpwd" 23 | identity_cert = "file:///var/secrets/est-id.pem" 24 | identity_pk = "pkcs11:slot-id=0;object=est-id?pin-value=1234" 25 | 26 | [cert_issuance.est.urls] 27 | default = "https://example.org/.well-known/est" 28 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | est-id = "pkcs11:slot-id=0;object=est%2Did?pin-value=1234" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id"] 12 | 13 | [[principal]] 14 | uid = 5555 15 | keys = ["est-id"] 16 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-est/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.local_ca] 4 | cert = "local-ca" 5 | pk = "local-ca" 6 | 7 | [cert_issuance.device-id] 8 | method = "local_ca" 9 | common_name = "my-device" 10 | 11 | [preloaded_certs] 12 | local-ca = "file:///var/secrets/local-ca.pem" 13 | 14 | [[principal]] 15 | uid = 5556 16 | certs = ["device-id"] 17 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | identity_cert = { method = "local_ca", common_name = "my-device" } 10 | 11 | [aziot_keys] 12 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 13 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 14 | 15 | [cert_issuance.local_ca] 16 | cert = "file:///var/secrets/local-ca.pem" 17 | pk = "pkcs11:slot-id=0;object=local-ca?pin-value=1234" 18 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | local-ca = "pkcs11:slot-id=0;object=local%2Dca?pin-value=1234" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id"] 12 | 13 | [[principal]] 14 | uid = 5555 15 | keys = ["local-ca"] 16 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11-localca/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | device-id = "file:///var/secrets/device-id.pem" 7 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | identity_cert = "file:///var/secrets/device-id.pem" 10 | identity_pk = "pkcs11:slot-id=0;object=device-id?pin-value=1234" 11 | 12 | [aziot_keys] 13 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 14 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | device-id = "pkcs11:slot-id=0;object=device%2Did?pin-value=1234" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id"] 12 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509-pkcs11/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | device-id = "file:///var/secrets/device-id.pem" 7 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "dps" 3 | global_endpoint = "https://global.azure-devices-provisioning.net/" 4 | id_scope = "0ab1234C5D6" 5 | 6 | [provisioning.attestation] 7 | method = "x509" 8 | registration_id = "my-device" 9 | identity_cert = "file:///var/secrets/device-id.pem" 10 | identity_pk = "file:///var/secrets/device-id.key.pem" 11 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "dps" 7 | global_endpoint = "https://global.azure-devices-provisioning.net/" 8 | scope_id = "0ab1234C5D6" 9 | 10 | [provisioning.attestation] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | registration_id = "my-device" 15 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/device-id.key.pem" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/dps-x509/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/dps-x509/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/config.toml: -------------------------------------------------------------------------------- 1 | local_gateway_hostname = "my-gateway-device" 2 | 3 | [provisioning] 4 | source = "manual" 5 | connection_string = "HostName=example.azure-devices.net;DeviceId=my-device;SharedAccessKey=YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGU=" 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-ide -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | local_gateway_hostname = "my-gateway-device" 7 | source = "manual" 8 | iothub_hostname = "example.azure-devices.net" 9 | device_id = "my-device" 10 | 11 | [provisioning.authentication] 12 | method = "sas" 13 | device_id_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/local-gateway/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/local-gateway/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/config.toml: -------------------------------------------------------------------------------- 1 | prefer_module_identity_cache = true 2 | 3 | [provisioning] 4 | source = "manual" 5 | connection_string = "HostName=example.azure-devices.net;DeviceId=my-device;SharedAccessKey=YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGU=" 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-ide -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = true 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "sas" 12 | device_id_pk = "device-id" 13 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-connection-string/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-connection-string/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "sas" 8 | device_id_pk = { value = "YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGU" } 9 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-ide -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "sas" 12 | device_id_pk = "device-id" 13 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key-no-pad/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "sas" 8 | device_id_pk = { value = "YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGU=" } 9 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-ide -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "sas" 12 | device_id_pk = "device-id" 13 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/aziot/keyd/device-id" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-symmetric-key/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.device-id] 4 | method = "est" 5 | url = "http://example.org/.well-known/est" 6 | username = "user" 7 | password = "password" 8 | identity_cert = "est-id-device-id" 9 | identity_pk = "est-id-device-id" 10 | expiry_days = 365 11 | common_name = "my-device" 12 | 13 | [preloaded_certs] 14 | est-id-device-id = "file:///var/secrets/est-id.pem" 15 | 16 | [[principal]] 17 | uid = 5556 18 | certs = ["device-id"] 19 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "x509" 8 | 9 | [provisioning.authentication.identity_cert] 10 | method = "est" 11 | common_name = "my-device" 12 | expiry_days = 365 13 | url = "http://example.org/.well-known/est" 14 | username = "user" 15 | password = "password" 16 | identity_cert = "file:///var/secrets/est-id.pem" 17 | identity_pk = "pkcs11:slot-id=0;object=est-id?pin-value=1234" 18 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | est-id-device-id = "pkcs11:slot-id=0;object=est%2Did?pin-value=1234" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | 11 | [[principal]] 12 | uid = 5555 13 | keys = ["est-id-device-id"] 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom-http/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.device-id] 4 | method = "est" 5 | url = "https://example.org/.well-known/est" 6 | username = "user" 7 | password = "password" 8 | identity_cert = "est-id-device-id" 9 | identity_pk = "est-id-device-id" 10 | expiry_days = 365 11 | common_name = "my-device" 12 | 13 | [preloaded_certs] 14 | est-id-device-id = "file:///var/secrets/est-id.pem" 15 | 16 | [[principal]] 17 | uid = 5556 18 | certs = ["device-id"] 19 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "x509" 8 | 9 | [provisioning.authentication.identity_cert] 10 | method = "est" 11 | common_name = "my-device" 12 | expiry_days = 365 13 | url = "https://example.org/.well-known/est" 14 | username = "user" 15 | password = "password" 16 | identity_cert = "file:///var/secrets/est-id.pem" 17 | identity_pk = "pkcs11:slot-id=0;object=est-id?pin-value=1234" 18 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | est-id-device-id = "pkcs11:slot-id=0;object=est%2Did?pin-value=1234" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | 11 | [[principal]] 12 | uid = 5555 13 | keys = ["est-id-device-id"] 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-x509-est-custom/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance.device-id] 4 | method = "est" 5 | url = "https://example.org/.well-known/est" 6 | username = "user" 7 | password = "password" 8 | identity_cert = "est-id-device-id" 9 | identity_pk = "est-id-device-id" 10 | expiry_days = 365 11 | 12 | [cert_issuance.device-id.subject] 13 | CN = "my-device" 14 | L = "AQ" 15 | ST = "Antarctica" 16 | 17 | [preloaded_certs] 18 | est-id-device-id = "file:///var/secrets/est-id.pem" 19 | 20 | [[principal]] 21 | uid = 5556 22 | certs = ["device-id"] 23 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "x509" 8 | 9 | [provisioning.authentication.identity_cert] 10 | method = "est" 11 | subject = { L = "AQ", ST = "Antarctica", CN = "my-device" } 12 | expiry_days = 365 13 | url = "https://example.org/.well-known/est" 14 | username = "user" 15 | password = "password" 16 | identity_cert = "file:///var/secrets/est-id.pem" 17 | identity_pk = "pkcs11:slot-id=0;object=est-id?pin-value=1234" 18 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | 15 | [provisioning.authentication.csr_subject] 16 | CN = "my-device" 17 | L = "AQ" 18 | ST = "Antarctica" 19 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | est-id-device-id = "pkcs11:slot-id=0;object=est%2Did?pin-value=1234" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | 11 | [[principal]] 12 | uid = 5555 13 | keys = ["est-id-device-id"] 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-x509-est-subject-dn/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | device-id = "file:///var/secrets/device-id.pem" 7 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "x509" 8 | identity_cert = "file:///var/secrets/device-id.pem" 9 | identity_pk = "pkcs11:slot-id=0;object=device-id?pin-value=1234" 10 | 11 | [aziot_keys] 12 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 13 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | pkcs11_base_slot = "pkcs11:slot-id=0?pin-value=1234" 4 | pkcs11_lib_path = "/usr/lib/libmypkcs11.so" 5 | 6 | [preloaded_keys] 7 | device-id = "pkcs11:slot-id=0;object=device%2Did?pin-value=1234" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id"] 12 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-x509-pkcs11/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | [cert_issuance] 4 | 5 | [preloaded_certs] 6 | device-id = "file:///var/secrets/device-id.pem" 7 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | iothub_hostname = "example.azure-devices.net" 4 | device_id = "my-device" 5 | 6 | [provisioning.authentication] 7 | method = "x509" 8 | identity_cert = "file:///var/secrets/device-id.pem" 9 | identity_pk = "file:///var/secrets/device-id.key.pem" 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | 5 | [provisioning] 6 | source = "manual" 7 | iothub_hostname = "example.azure-devices.net" 8 | device_id = "my-device" 9 | 10 | [provisioning.authentication] 11 | method = "x509" 12 | identity_cert = "device-id" 13 | identity_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509/keyd.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | 4 | [preloaded_keys] 5 | device-id = "file:///var/secrets/device-id.key.pem" 6 | 7 | [[principal]] 8 | uid = 5556 9 | keys = ["aziot_identityd_master_id", "device-id"] 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/manual-x509/tpmd.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/iot-identity-service/0c33b7b80a3fff060aa3e8e1ba226901e4154b6a/aziotctl/aziotctl-common/test-files/apply/manual-x509/tpmd.toml -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/certd.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | max_requests = 30 3 | 4 | [cert_issuance] 5 | 6 | [preloaded_certs] 7 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/config.toml: -------------------------------------------------------------------------------- 1 | [provisioning] 2 | source = "manual" 3 | connection_string = "HostName=example.azure-devices.net;DeviceId=my-device;SharedAccessKey=YXppb3QtaWRlbnRpdHktc2VydmljZXxhemlvdC1pZGU=" 4 | 5 | [aziot_max_requests] 6 | keyd = 20 7 | certd = 30 8 | tpmd = 40 9 | identityd = 50 10 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/device-id: -------------------------------------------------------------------------------- 1 | aziot-identity-service|aziot-ide -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/identityd.toml: -------------------------------------------------------------------------------- 1 | hostname = "my-device" 2 | homedir = "/var/lib/aziot/identityd" 3 | prefer_module_identity_cache = false 4 | max_requests = 50 5 | 6 | [provisioning] 7 | source = "manual" 8 | iothub_hostname = "example.azure-devices.net" 9 | device_id = "my-device" 10 | 11 | [provisioning.authentication] 12 | method = "sas" 13 | device_id_pk = "device-id" 14 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/keyd.toml: -------------------------------------------------------------------------------- 1 | max_requests = 20 2 | 3 | [aziot_keys] 4 | homedir_path = "/var/lib/aziot/keyd" 5 | 6 | [preloaded_keys] 7 | device-id = "file:///var/secrets/aziot/keyd/device-id" 8 | 9 | [[principal]] 10 | uid = 5556 11 | keys = ["aziot_identityd_master_id", "device-id"] 12 | -------------------------------------------------------------------------------- /aziotctl/aziotctl-common/test-files/apply/throttle-limits/tpmd.toml: -------------------------------------------------------------------------------- 1 | max_requests = 40 2 | -------------------------------------------------------------------------------- /aziotctl/src/config/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | mod apply; 4 | mod mp; 5 | 6 | #[derive(clap::Subcommand)] 7 | pub(crate) enum Options { 8 | /// Apply the configuration to the Azure IoT Identity Service and related services. 9 | Apply(apply::Options), 10 | 11 | /// Quick-create a new configuration for manual provisioning with a connection string. 12 | Mp(mp::Options), 13 | } 14 | 15 | pub(crate) fn run(options: Options) -> anyhow::Result<()> { 16 | match options { 17 | Options::Apply(options) => apply::run(options), 18 | Options::Mp(options) => mp::run(options), 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /aziotctl/src/internal/check/checks/up_to_date_configs.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use anyhow::anyhow; 4 | use serde::Serialize; 5 | 6 | use aziotctl_common::check_last_modified::{check_last_modified, LastModifiedError}; 7 | 8 | use crate::internal::check::{CheckResult, Checker, CheckerCache, CheckerMeta, CheckerShared}; 9 | 10 | #[derive(Serialize, Default)] 11 | pub struct UpToDateConfigs {} 12 | 13 | #[async_trait::async_trait] 14 | impl Checker for UpToDateConfigs { 15 | fn meta(&self) -> CheckerMeta { 16 | CheckerMeta { 17 | id: "configs-up-to-date", 18 | description: "daemon configurations up-to-date with config.toml", 19 | } 20 | } 21 | 22 | #[allow(clippy::unused_async)] 23 | async fn execute(&mut self, _shared: &CheckerShared, _cache: &mut CheckerCache) -> CheckResult { 24 | match check_last_modified(&["keyd", "certd", "identityd", "tpmd"]) { 25 | Ok(()) => CheckResult::Ok, 26 | Err(LastModifiedError::Ignored) => CheckResult::Ignored, 27 | Err(LastModifiedError::Warning(message)) => CheckResult::Warning(anyhow!(message)), 28 | Err(LastModifiedError::Failed(error)) => CheckResult::Failed(error.into()), 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /aziotctl/src/internal/check/util.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use anyhow::anyhow; 4 | 5 | use crate::internal::common::CertificateValidity; 6 | 7 | use super::CheckResult; 8 | 9 | pub trait CertificateValidityExt { 10 | fn to_check_result(&self) -> anyhow::Result; 11 | } 12 | 13 | impl CertificateValidityExt for CertificateValidity { 14 | fn to_check_result(&self) -> anyhow::Result { 15 | let now = chrono::Utc::now(); 16 | if self.not_before > now { 17 | Err(anyhow!( 18 | "{} '{}' has not-before time {} which is in the future", 19 | self.cert_name, 20 | self.cert_id, 21 | self.not_before, 22 | )) 23 | } else if self.not_after < now { 24 | Err(anyhow!( 25 | "{} '{}' expired at {}", 26 | self.cert_name, 27 | self.cert_id, 28 | self.not_after, 29 | )) 30 | } else if self.not_after < now + chrono::Duration::days(7) { 31 | Ok(CheckResult::Warning(anyhow!( 32 | "{} '{}' will expire soon ({}, in {} days)", 33 | self.cert_name, 34 | self.cert_id, 35 | self.not_after, 36 | (self.not_after - now).num_days(), 37 | ))) 38 | } else { 39 | Ok(CheckResult::Ok) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /aziotctl/src/internal/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | pub mod check; 4 | pub mod common; 5 | -------------------------------------------------------------------------------- /aziotctl/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow( 6 | clippy::default_trait_access, 7 | clippy::let_and_return, 8 | let_underscore_drop, 9 | clippy::let_unit_value, 10 | clippy::module_name_repetitions, 11 | clippy::similar_names, 12 | clippy::struct_excessive_bools, 13 | clippy::too_many_lines, 14 | clippy::type_complexity 15 | )] 16 | 17 | use anyhow::Result; 18 | use clap::Parser; 19 | 20 | mod internal; 21 | 22 | // Subcommands 23 | mod check; 24 | mod check_list; 25 | mod config; 26 | mod system; 27 | 28 | async fn try_main() -> Result<()> { 29 | match Options::parse() { 30 | Options::Check(cfg) => check::check(cfg).await?, 31 | Options::CheckList(cfg) => check_list::check_list(cfg)?, 32 | Options::Config(cfg) => config::run(cfg)?, 33 | Options::System(cfg) => system::system(cfg).await?, 34 | } 35 | 36 | Ok(()) 37 | } 38 | 39 | #[tokio::main] 40 | async fn main() { 41 | if let Err(err) = try_main().await { 42 | eprintln!("{err:?}"); 43 | } 44 | } 45 | 46 | #[derive(Parser)] 47 | #[command(version)] 48 | enum Options { 49 | /// Work with the configuration of the Azure IoT Identity Service and related services. 50 | #[command(subcommand)] 51 | Config(config::Options), 52 | 53 | /// Check for common config and deployment issues. 54 | Check(check::Options), 55 | 56 | /// List the checks that are run for 'aziotctl check' 57 | CheckList(check_list::Options), 58 | 59 | /// Use system helper commands 60 | #[command(subcommand)] 61 | System(system::Options), 62 | } 63 | -------------------------------------------------------------------------------- /aziotd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziotd" 3 | version = "1.5.5" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | homepage = "https://azure.github.io/iot-identity-service/" 7 | description = "aziotd is the main binary for the IoT Identity Service and related services." 8 | license = "MIT" 9 | 10 | [dependencies] 11 | backtrace = "0.3" 12 | hyper = "0.14" 13 | log = "0.4" 14 | serde = "1" 15 | tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync"] } 16 | 17 | aziot-certd = { path = "../cert/aziot-certd" } 18 | aziot-identityd = { path = "../identity/aziot-identityd" } 19 | aziot-keyd = { path = "../key/aziot-keyd" } 20 | aziot-tpmd = { path = "../tpm/aziot-tpmd" } 21 | config-common = { path = "../config-common" } 22 | http-common = { path = "../http-common" } 23 | logger = { path = "../logger" } 24 | -------------------------------------------------------------------------------- /aziotd/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #[derive(Debug)] 4 | pub(crate) struct Error(pub(crate) ErrorKind, pub(crate) backtrace::Backtrace); 5 | 6 | #[derive(Debug)] 7 | pub(crate) enum ErrorKind { 8 | GetProcessName(std::borrow::Cow<'static, str>), 9 | ReadConfig(Box), 10 | Service(Box), 11 | } 12 | 13 | impl std::fmt::Display for ErrorKind { 14 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 | match self { 16 | ErrorKind::GetProcessName(message) => write!(f, "could not read argv[0]: {message}"), 17 | ErrorKind::ReadConfig(_) => f.write_str("could not read config"), 18 | ErrorKind::Service(_) => f.write_str("service encountered an error"), 19 | } 20 | } 21 | } 22 | 23 | impl std::error::Error for ErrorKind { 24 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 25 | #[allow(clippy::match_same_arms)] 26 | match self { 27 | ErrorKind::GetProcessName(_) => None, 28 | ErrorKind::ReadConfig(err) => Some(&**err), 29 | ErrorKind::Service(err) => Some(&**err), 30 | } 31 | } 32 | } 33 | 34 | impl From for Error { 35 | fn from(err: ErrorKind) -> Self { 36 | Error(err, Default::default()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cert/aziot-cert-client-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-cert-client-async" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | http = "0.2" 9 | hyper = "0.14" 10 | percent-encoding = "2" 11 | 12 | aziot-cert-common-http = { path = "../aziot-cert-common-http" } 13 | aziot-key-common = { path = "../../key/aziot-key-common" } 14 | http-common = { path = "../../http-common" } 15 | -------------------------------------------------------------------------------- /cert/aziot-cert-common-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-cert-common-http" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | serde = { version = "1", features = ["derive"] } 9 | 10 | aziot-key-common = { path = "../../key/aziot-key-common" } 11 | -------------------------------------------------------------------------------- /cert/aziot-cert-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-cert-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /cert/aziot-cert-common/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | -------------------------------------------------------------------------------- /cert/aziot-certd-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-certd-config" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | hex = "0.4" 10 | libc = "0.2" 11 | openssl = "0.10" 12 | serde = { version = "1", features = ["derive"] } 13 | serde_with = "2" 14 | url = { version = "2", features = ["serde"] } 15 | 16 | cert-renewal = { path = "../cert-renewal" } 17 | http-common = { path = "../../http-common" } 18 | 19 | [dev-dependencies] 20 | toml = "0.7" 21 | -------------------------------------------------------------------------------- /cert/aziot-certd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-certd" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | async-recursion = "1" 10 | async-trait = "0.1" 11 | base64 = "0.21" 12 | foreign-types-shared = "0.1" 13 | futures-util = "0.3" 14 | hex = "0.4" 15 | http = "0.2" 16 | hyper = "0.14" 17 | hyper-openssl = "0.9" 18 | lazy_static = "1" 19 | libc = "0.2" 20 | log = "0.4" 21 | openssl = "0.10" 22 | openssl-sys = "0.9.86" # for openssl_sys::PKCS7 23 | percent-encoding = "2" 24 | regex = "1" 25 | serde = "1" 26 | serde_json = "1" 27 | tokio = { version = "1", features = ["parking_lot", "sync", "time"] } 28 | url = "2" 29 | wildmatch = "2" 30 | 31 | aziot-cert-common-http = { path = "../aziot-cert-common-http" } 32 | aziot-certd-config = { path = "../aziot-certd-config" } 33 | aziot-key-client = { path = "../../key/aziot-key-client" } 34 | aziot-key-client-async = { path = "../../key/aziot-key-client-async" } 35 | aziot-key-common = { path = "../../key/aziot-key-common" } 36 | aziot-key-common-http = { path = "../../key/aziot-key-common-http" } 37 | aziot-key-openssl-engine = { path = "../../key/aziot-key-openssl-engine" } 38 | cert-renewal = { path = "../cert-renewal" } 39 | config-common = { path = "../../config-common", features = ["watcher"] } 40 | http-common = { path = "../../http-common" } 41 | openssl2 = { path = "../../openssl2" } 42 | -------------------------------------------------------------------------------- /cert/aziot-certd/aziot-certd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Certificates Service 3 | Requires=aziot-certd.socket 4 | After=aziot-certd.socket 5 | 6 | [Service] 7 | Environment="LD_LIBRARY_PATH=@private-libs@" 8 | ExecStart=@libexecdir@/aziot-identity-service/aziot-certd 9 | KillMode=process 10 | Restart=on-failure 11 | RestartSec=5s 12 | User=@user_aziotcs@ 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /cert/aziot-certd/aziot-certd.socket.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Certificates Service API socket 3 | PartOf=aziot-certd.service 4 | 5 | [Socket] 6 | ListenStream=@socket_dir@/certd.sock 7 | SocketMode=0660 8 | DirectoryMode=0755 9 | SocketUser=@user_aziotcs@ 10 | SocketGroup=@user_aziotcs@ 11 | 12 | [Install] 13 | WantedBy=sockets.target 14 | -------------------------------------------------------------------------------- /cert/aziot-certd/config/unix/default.toml: -------------------------------------------------------------------------------- 1 | homedir_path = "/var/lib/aziot/certd" 2 | 3 | # [cert_issuance] 4 | 5 | # [preloaded_certs] 6 | -------------------------------------------------------------------------------- /cert/aziot-certd/src/http/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | mod create; 4 | mod get_or_import_or_delete; 5 | 6 | #[derive(Clone)] 7 | pub struct Service { 8 | pub(crate) api: std::sync::Arc>, 9 | } 10 | 11 | http_common::make_service! { 12 | service: Service, 13 | api_version: aziot_cert_common_http::ApiVersion, 14 | routes: [ 15 | create::Route, 16 | get_or_import_or_delete::Route, 17 | ], 18 | } 19 | 20 | fn to_http_error(err: &crate::Error) -> http_common::server::Error { 21 | let error_message = http_common::server::error_to_message(err); 22 | 23 | // TODO: When we get distributed tracing, associate these logs with the tracing ID. 24 | for line in error_message.lines() { 25 | log::log!( 26 | match err { 27 | crate::Error::Internal(_) => log::Level::Error, 28 | _ => log::Level::Info, 29 | }, 30 | "!!! {}", 31 | line, 32 | ); 33 | } 34 | 35 | match err { 36 | // Do not use error_message because we don't want to leak internal errors to the client. 37 | // Just return the top-level error, ie "internal error" 38 | crate::Error::Internal(_) => http_common::server::Error { 39 | status_code: hyper::StatusCode::INTERNAL_SERVER_ERROR, 40 | message: err.to_string().into(), 41 | }, 42 | 43 | crate::Error::InvalidParameter(_, _) => http_common::server::Error { 44 | status_code: hyper::StatusCode::BAD_REQUEST, 45 | message: error_message.into(), 46 | }, 47 | 48 | crate::Error::Unauthorized(_, _) => http_common::server::Error { 49 | status_code: hyper::StatusCode::UNAUTHORIZED, 50 | message: err.to_string().into(), 51 | }, 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /cert/cert-renewal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cert-renewal" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | async-trait = "0.1" 9 | chrono = "0.4" 10 | futures-util = "0.3" 11 | log = "0.4" 12 | openssl = "0.10" 13 | serde = "1" 14 | tokio = { version = "1", features = ["macros", "parking_lot", "rt", "sync", "time"] } 15 | 16 | [dev-dependencies] 17 | serial_test = "1" 18 | toml = "0.7" 19 | 20 | test-common = { path = "../../test-common" } 21 | -------------------------------------------------------------------------------- /cert/cert-renewal/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #[derive(Clone, Debug)] 4 | pub enum Error { 5 | Fatal(String), 6 | Retryable(String), 7 | } 8 | 9 | impl Error { 10 | pub fn fatal_error(message: impl std::fmt::Display) -> Self { 11 | Error::Fatal(message.to_string()) 12 | } 13 | 14 | pub fn retryable_error(message: impl std::fmt::Display) -> Self { 15 | Error::Retryable(message.to_string()) 16 | } 17 | } 18 | 19 | impl std::fmt::Display for Error { 20 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 21 | let message = match self { 22 | Error::Fatal(message) | Error::Retryable(message) => message, 23 | }; 24 | 25 | write!(f, "{message}") 26 | } 27 | } 28 | 29 | impl std::error::Error for Error {} 30 | 31 | impl std::convert::From for std::io::Error { 32 | fn from(err: Error) -> std::io::Error { 33 | let message = match err { 34 | Error::Fatal(message) | Error::Retryable(message) => message, 35 | }; 36 | 37 | std::io::Error::new(std::io::ErrorKind::Other, message) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ci/code-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euxo pipefail 4 | 5 | cd /src 6 | 7 | . ./ci/install-test-deps.sh 8 | 9 | if [ "$SKIP_TSS_MINIMAL" = 0 ]; then 10 | TPM_STATE="$(mktemp -d)" 11 | LD_LIBRARY_PATH=/usr/local/lib swtpm socket \ 12 | --tpm2 \ 13 | --tpmstate dir="$TPM_STATE" \ 14 | --port 2321 \ 15 | --ctrl type=tcp,port=2322 \ 16 | --flags not-need-init,startup-clear & 17 | SWTPM_PID=$! 18 | trap "kill '$SWTPM_PID'; rm -rf '$TPM_STATE';" EXIT 19 | fi 20 | 21 | make SKIP_TSS_MINIMAL="$SKIP_TSS_MINIMAL" codecov 22 | -------------------------------------------------------------------------------- /ci/e2e-tests/az-login.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | echo 'Installing and updating azure-iot extension...' >&2 5 | az extension add --name azure-iot 6 | az extension update --name azure-iot 7 | echo 'Installed and updated azure-iot extension' >&2 8 | 9 | 10 | echo 'Logging in to Azure...' >&2 11 | >/dev/null az login --identity 12 | echo 'Logged in to Azure' >&2 13 | 14 | if [ -n "${AZURE_LOCATION:-}" ]; then 15 | az configure --defaults "location=$AZURE_LOCATION" 16 | fi 17 | 18 | az config set core.collect_telemetry=no 19 | -------------------------------------------------------------------------------- /ci/e2e-tests/suite-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # Suite ID. Used as resource tag for all Azure resources created in this suite. 5 | suite_id="${BRANCH:-unknown}:$GITHUB_RUN_ID:$GITHUB_RUN_NUMBER" 6 | echo "suite_id: $suite_id" >&2 7 | 8 | # Common name for all suite-level Azure resources 9 | suite_common_resource_name="$(printf '%s' "$suite_id" | tr -C 'a-z0-9' '-')" 10 | echo "suite_common_resource_name: $suite_common_resource_name" >&2 11 | 12 | # Variables related to the DPS custom allocation policy 13 | dps_allocation_function_name='DpsCustomAllocation' 14 | dps_allocation_functionapp_name="alloc-app-${suite_common_resource_name}" 15 | foo_devices_iot_hub="${suite_common_resource_name}-foo-devices" 16 | dps_allocation_storage_account="$(printf '%s' "$suite_id" | tr '[:upper:]' '[:lower:]' | tr -d -C 'a-z0-9')" 17 | -------------------------------------------------------------------------------- /ci/e2e-tests/suite-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: 4 | # 5 | # ./ci/e2e-tests/suite-setup.sh 6 | # 7 | # See https://github.com/Azure/iot-identity-service/blob/main/docs-dev/e2e-tests.md for details of some env vars that need to be defined. 8 | 9 | set -euo pipefail 10 | 11 | echo "$0 $*" >&2 12 | 13 | 14 | GITHUB_WORKSPACE="${GITHUB_WORKSPACE:-$PWD}" 15 | 16 | . "$GITHUB_WORKSPACE/ci/e2e-tests/suite-common.sh" 17 | 18 | 19 | . "$GITHUB_WORKSPACE/ci/e2e-tests/az-login.sh" 20 | 21 | source "$GITHUB_WORKSPACE/ci/e2e-tests/helper-functions.sh" 22 | 23 | 24 | createHub "$suite_common_resource_name" 25 | 26 | echo 'Creating DPS...' >&2 27 | 28 | dps_resource_id="$( 29 | az iot dps create \ 30 | --resource-group "$AZURE_RESOURCE_GROUP_NAME" \ 31 | --name "$suite_common_resource_name" \ 32 | --tags "suite_id=$suite_id" \ 33 | --query 'id' --output tsv 34 | )" 35 | 36 | createDpsLinkedHub $suite_common_resource_name $suite_common_resource_name $dps_resource_id "suite_id=$suite_id" 37 | 38 | echo 'Created DPS' >&2 39 | 40 | installTestTools 41 | 42 | echo 'Setting up custom allocation policy...' 43 | 44 | setupCustomAllocationPolicy 45 | 46 | echo 'Done setting up custom allocation policy' 47 | -------------------------------------------------------------------------------- /ci/e2e-tests/test-cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: 4 | # 5 | # ./ci/e2e-tests/test-cleanup.sh 6 | # 7 | # See https://github.com/Azure/iot-identity-service/blob/main/docs-dev/e2e-tests.md for details of some env vars that need to be defined. 8 | # 9 | # : 10 | # manual-symmetric-key 11 | 12 | set -euo pipefail 13 | 14 | 15 | echo "$0 $*" >&2 16 | 17 | 18 | GITHUB_WORKSPACE="${GITHUB_WORKSPACE:-$PWD}" 19 | 20 | . "$GITHUB_WORKSPACE/ci/e2e-tests/test-common.sh" 21 | 22 | 23 | # `az resource list` has `--tag` to filter, but it cannot be combined with `--resource-group`, 24 | # so we need to query with `--resource-group` and then filter using tags ourselves. 25 | # 26 | # Also, sometimes deleting resources fails because `az resource delete` doesn't respect inter-resource dependencies. 27 | # So keep trying it in a loop as long as there are still resources that match. 28 | 29 | set +eo pipefail 30 | 31 | # Change out of $working_directory because we're going to delete it. 32 | # It's not fatal to remain in a deleted directory, but it does stop bash and az spamming stderr 33 | # that their cwd does not exist. 34 | cd ~ 35 | 36 | rm -rf "$working_directory" 37 | 38 | 39 | echo 'Deleting resources...' >&2 40 | while :; do 41 | ids="$( 42 | az resource list --resource-group "$AZURE_RESOURCE_GROUP_NAME" | 43 | jq --arg test_id "$test_id" -r '.[] | select(.tags.test_id == $test_id).id' 44 | )" 45 | printf 'Resources remaining:\n%s\n' "$ids" 46 | if [ -z "$ids" ]; then 47 | break 48 | fi 49 | 50 | <<< "$ids" timeout 30s xargs az resource delete --ids >/dev/null 51 | 52 | sleep 1 53 | echo 'Retrying...' >&2 54 | done 55 | 56 | echo 'Deleted resources' >&2 57 | -------------------------------------------------------------------------------- /ci/e2e-tests/test-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | . "$GITHUB_WORKSPACE/ci/e2e-tests/suite-common.sh" 5 | 6 | 7 | test_name="$1" 8 | 9 | 10 | # Test ID. Used as resource tag for all Azure resources created in this test. 11 | test_id="${BRANCH:-unknown}:$GITHUB_RUN_ID:$GITHUB_RUN_NUMBER:$OS:$test_name" 12 | echo "test_id: $test_id" >&2 13 | 14 | # Common name for all test-level Azure resources 15 | test_common_resource_name="$(printf '%s' "$test_id" | tr -C 'a-z0-9' '-')" 16 | echo "test_common_resource_name: $test_common_resource_name" >&2 17 | 18 | # Temp directory used as scratch space to store the downloaded package from GitHub 19 | # and the config files for the package that are scp'd to the test VM. 20 | working_directory="/tmp/iot-identity-service-e2e-tests-$test_common_resource_name" 21 | echo "working_directory: $working_directory" >&2 22 | -------------------------------------------------------------------------------- /ci/mock-iot-tests/mock-iot-cert-gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | >mock_iot_certs.conf cat <<-EOF 6 | [ root_cert ] 7 | basicConstraints = critical, CA:TRUE 8 | keyUsage = keyCertSign 9 | 10 | [ server_cert ] 11 | basicConstraints = CA:FALSE 12 | keyUsage = digitalSignature, keyEncipherment 13 | extendedKeyUsage = serverAuth 14 | EOF 15 | 16 | # Generate test root CA certificate. 17 | openssl genrsa -out root_cert_key.pem &> /dev/null 18 | openssl req -new -key root_cert_key.pem -subj "/CN=Mock_IoT_Test_Root" -out root_req.pem 19 | 20 | openssl x509 -req \ 21 | -in root_req.pem \ 22 | -extfile mock_iot_certs.conf -extensions root_cert \ 23 | -signkey root_cert_key.pem -sha256 \ 24 | -out root_cert.pem &> /dev/null 25 | 26 | # Generate test server certificate. 27 | openssl genrsa -out server_cert_key.pem &> /dev/null 28 | 29 | # mock-iot-server always uses hostname localhost, so its server certificate must always have CN or SAN localhost. 30 | openssl req -new -key server_cert_key.pem -subj "/CN=localhost" -out server_req.pem 31 | 32 | openssl x509 -req \ 33 | -in server_req.pem \ 34 | -extfile mock_iot_certs.conf -extensions server_cert \ 35 | -CAcreateserial -sha256 \ 36 | -CA root_cert.pem -CAkey root_cert_key.pem \ 37 | -out server_cert.pem &> /dev/null 38 | 39 | cat server_cert.pem root_cert.pem > server_cert_chain.pem 40 | 41 | echo "Generated test root CA certificate:" 42 | echo " - $(pwd)/root_cert.pem" 43 | echo "" 44 | echo "Generated test server certificate:" 45 | echo " - cert chain: $(pwd)/server_cert_chain.pem" 46 | echo " - key: $(pwd)/server_cert_key.pem" 47 | -------------------------------------------------------------------------------- /ci/test-aziot-key-openssl-engine-shared.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euxo pipefail 4 | 5 | cd /src 6 | 7 | . ./ci/install-runtime-deps.sh 8 | 9 | case "$OS" in 10 | 'debian:11'|'debian:12'|'platform:el8'|'platform:el9'|'ubuntu:20.04'|'ubuntu:22.04'|'ubuntu:24.04') 11 | cp \ 12 | ./target/debug/libaziot_key_openssl_engine_shared.so \ 13 | "$(openssl version -e | sed -E 's/^ENGINESDIR: "(.*)"$/\1/')/aziot_keys.so" 14 | ;; 15 | 16 | *) 17 | echo "Unsupported OS $OS." >&2 18 | exit 1 19 | ;; 20 | esac 21 | 22 | chmod +x ./target/debug/aziotd 23 | chmod +x ./target/debug/aziot-key-openssl-engine-shared-test 24 | 25 | case "${PKCS11_BACKEND:-}" in 26 | 'softhsm') 27 | TOKEN='Key pairs' 28 | USER_PIN='1234' 29 | softhsm2-util --init-token --free --label "$TOKEN" --so-pin "so$USER_PIN" --pin "$USER_PIN" 30 | export PKCS11_BASE_SLOT="pkcs11:token=$TOKEN?pin-value=$USER_PIN" 31 | ;; 32 | 33 | '') 34 | ;; 35 | 36 | *) 37 | echo "Unsupported PKCS#11 backend $PKCS11_BACKEND" >&2 38 | exit 1 39 | ;; 40 | esac 41 | 42 | ./key/test-aziot-key-openssl-engine-shared.sh 43 | -------------------------------------------------------------------------------- /ci/test-basic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euxo pipefail 4 | 5 | cd /src 6 | 7 | . ./ci/install-test-deps.sh 8 | 9 | if [ "$SKIP_TSS_MINIMAL" = 0 ]; then 10 | libpath=/usr/local/lib 11 | if [ "$USE_SWTPM_PKG" = 1 ]; then 12 | libpath= 13 | fi 14 | 15 | TPM_STATE="$(mktemp -d)" 16 | LD_LIBRARY_PATH=$libpath swtpm socket \ 17 | --tpm2 \ 18 | --tpmstate dir="$TPM_STATE" \ 19 | --port 2321 \ 20 | --ctrl type=tcp,port=2322 \ 21 | --flags not-need-init,startup-clear & 22 | SWTPM_PID=$! 23 | trap "kill '$SWTPM_PID'; rm -rf '$TPM_STATE';" EXIT 24 | fi 25 | 26 | make SKIP_TSS_MINIMAL="$SKIP_TSS_MINIMAL" VENDOR_LIBTSS="${VENDOR_LIBTSS:-0}" V=1 test-release 27 | -------------------------------------------------------------------------------- /config-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "config-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | async-trait = { version = "0.1", optional = true } 10 | log = { version = "0.4", optional = true } 11 | notify = { version = "4", optional = true } 12 | serde = "1" 13 | tokio = { version = "1", features = ["parking_lot", "rt", "sync"], optional = true } 14 | toml = "0.7" 15 | 16 | 17 | [features] 18 | watcher = ["async-trait", "log", "notify", "tokio"] 19 | -------------------------------------------------------------------------------- /config-common/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #[derive(Debug)] 4 | pub enum Error { 5 | ReadConfig( 6 | Option, 7 | Box, 8 | ), 9 | } 10 | 11 | impl std::fmt::Display for Error { 12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 13 | match self { 14 | Error::ReadConfig(Some(path), _) => { 15 | write!(f, "could not read config from {}", path.display()) 16 | } 17 | Error::ReadConfig(None, _) => f.write_str("could not read config"), 18 | } 19 | } 20 | } 21 | 22 | impl std::error::Error for Error { 23 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 24 | #[allow(clippy::match_same_arms)] 25 | match self { 26 | Error::ReadConfig(_, err) => Some(&**err), 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contrib/debian/changelog: -------------------------------------------------------------------------------- 1 | aziot-identity-service (@version@-@release@) unstable; urgency=medium 2 | 3 | * New release 4 | 5 | -- "Azure IoT Edge Devs" <> Wed, 16 Sep 2020 03:18:23 +0000 6 | -------------------------------------------------------------------------------- /contrib/debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /contrib/debian/control: -------------------------------------------------------------------------------- 1 | Source: aziot-identity-service 2 | Section: admin 3 | Priority: optional 4 | Maintainer: Azure IoT Edge Devs 5 | Build-Depends: debhelper (>=9.20160709) 6 | Standards-Version: 3.9.8 7 | Homepage: https://github.com/azure/iot-identity-service 8 | Vcs-Browser: https://github.com/azure/iot-identity-service 9 | Vcs-Git: https://github.com/azure/iot-identity-service 10 | 11 | Package: aziot-identity-service 12 | Architecture: any 13 | Depends: ${shlibs:Depends}, ${misc:Depends}, psmisc 14 | Conflicts: iotedge, libiothsm-std 15 | Description: Azure IoT Identity Service and related services 16 | This package contains the Azure IoT device runtime, comprised of the following services: 17 | . 18 | - aziot-identityd - The Azure IoT Identity Service 19 | - aziot-certd - The Azure IoT Certificates Service 20 | - aziot-keyd - The Azure IoT Keys Service 21 | - aziot-tpmd - The Azure IoT TPM Service 22 | . 23 | This package also contains the following libraries: 24 | . 25 | - libaziot_keys.so - The library used by the Keys Service to communicate with HSMs for key operations. 26 | - /aziot_keys.so - An openssl engine that can be used to work with asymmetric keys managed by the Azure IoT Keys Service. 27 | . 28 | Lastly, this package contains the aziotctl binary that is used to configure and manage the services. 29 | -------------------------------------------------------------------------------- /contrib/debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: aziot-identity-service 3 | Source: https://github.com/azure/iot-identity-service 4 | 5 | Files: * 6 | Copyright: Copyright (c) Microsoft Corporation 7 | License: MIT 8 | Microsoft Azure IoT Identity Service 9 | Copyright (c) Microsoft Corporation 10 | 11 | MIT license 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE 29 | -------------------------------------------------------------------------------- /contrib/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /contrib/enterprise-linux/00-aziot.preset: -------------------------------------------------------------------------------- 1 | # Enable the sockets for aziot services. 2 | # The services themselves only start if data is written to their respective socket. 3 | 4 | enable aziot-certd.socket 5 | enable aziot-identityd.socket 6 | enable aziot-keyd.socket 7 | enable aziot-tpmd.socket 8 | -------------------------------------------------------------------------------- /contrib/mariner/aziot-identity-service.signatures.json: -------------------------------------------------------------------------------- 1 | { 2 | "Signatures": { 3 | "aziot-identity-service-@@VERSION@@.tar.gz": "0000000000000000000000000000000000000000000000000000000000000000", 4 | "cbindgen-@@CBINDGEN_VERSION@@.tar.gz": "0000000000000000000000000000000000000000000000000000000000000000", 5 | "rust-bindgen-@@BINDGEN_VERSION@@.tar.gz": "0000000000000000000000000000000000000000000000000000000000000000", 6 | "rust.tar.gz": "0000000000000000000000000000000000000000000000000000000000000000" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /contrib/snap/command-chain/launch-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | log_level="$(snapctl get log-level)" 6 | if [ -n "$log_level" ]; then 7 | export AZIOT_LOG="$log_level" 8 | fi 9 | 10 | export LD_LIBRARY_PATH="$SNAP/lib/aziot-identity-service${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" 11 | 12 | exec "$@" 13 | -------------------------------------------------------------------------------- /docs-dev/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default 2 | 3 | default: 4 | rm -f img/*.svg 5 | plantuml -tsvg -o $$PWD/img/ plantuml/*.plantuml 6 | -------------------------------------------------------------------------------- /docs-dev/README.md: -------------------------------------------------------------------------------- 1 | # Developer documentation 2 | 3 | These docs are meant for developers working on this repository who need to build the services from source, deploy in testing environments, etc. 4 | 5 | If you are not a developer working on this repository, please go to user docs at instead. 6 | 7 | - [Building the services](building.md) 8 | 9 | - [Running the services locally](running/index.md) 10 | 11 | - [Building the packages](packages.md) 12 | 13 | - [End-to-end tests](e2e-tests.md) 14 | 15 | - [Provisioning using EST, with certificates issued by EST (On-prem PKI)](est-ca.md) 16 | 17 | - [TPM Service API docs](tpm-service.md) 18 | 19 | - [OpenSSL engine internals](openssl-engine-internals.md) 20 | -------------------------------------------------------------------------------- /docs-dev/plantuml/est-ca-device-setup.plantuml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | title Device Setup 4 | 5 | participant "Operator" as operator 6 | 7 | box Device #LightBlue 8 | participant "Device" as device 9 | participant "Module Runtime" as mr 10 | participant "Identity Service" as is 11 | participant "Keys Service" as ks 12 | participant "Certificates Service" as cs 13 | end box 14 | 15 | autonumber 16 | 17 | operator -> device: Install OS and HSM-specific PKCS#11 library 18 | 19 | operator -> device: Generate new private key in HSM\n(via pkcs11-tool, p11tool, provider-specific tool, etc) 20 | operator -> device: Create CSR for bootstrap ID cert using private key\n(via openssl, etc) 21 | operator -> operator: Sign CSR using device identity CA 22 | operator -> device: Save bootstrap ID cert on the filesystem 23 | 24 | operator -> ks: Configure Keys Service to preload the bootstrap cert's private key 25 | note left 26 | See [1] below diagram for 27 | configuration example 28 | end note 29 | 30 | operator -> cs: Configure Certificates Service to preload the bootstrap cert 31 | note left 32 | See [2] below diagram for 33 | configuration example 34 | end note 35 | 36 | operator -> is: Configure Identity Service with device provisioning configuration 37 | note left 38 | See [3] below diagram for 39 | configuration example 40 | end note 41 | 42 | operator -> mr: Start Module Runtime 43 | operator -> is: Start Identity Service 44 | operator -> ks: Start Keys Service 45 | operator -> cs: Start Certificates Service 46 | 47 | @enduml 48 | -------------------------------------------------------------------------------- /docs-dev/plantuml/old-component-overview.plantuml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Data flow - old architecture 3 | cloud "DPS Service" { 4 | [DPS Gateway] <> 5 | } 6 | 7 | cloud "IoT Hub Service" { 8 | [IoTHub Gateway] <> 9 | } 10 | 11 | node "Edge Security Daemon" { 12 | folder "ESD Legacy Service" { 13 | [ESD API Server] 14 | } 15 | } 16 | node "Edge Agent" { 17 | [ESD EA Client] 18 | [IoTHub EA Client] 19 | } 20 | node "Edge Hub" { 21 | [ESD EH Client] 22 | [IoTHub EH Client] 23 | } 24 | 25 | database "HSM" 26 | 27 | 28 | [ESD EH Client] --> [ESD API Server] : IPC 29 | [ESD EA Client] --> [ESD API Server] : IPC 30 | 31 | [ESD API Server] -down-> HSM : libiothsm 32 | [ESD API Server] -left-> [DPS Gateway] : HTTPS 33 | 34 | [ESD API Server] -up-> [IoTHub Gateway] : HTTPS 35 | [IoTHub EH Client] <-up-> [IoTHub Gateway] : AMQP (EH Module) 36 | [IoTHub EA Client] -up-> [IoTHub Gateway] : HTTPS 37 | 38 | skinparam component { 39 | backgroundColor White 40 | } 41 | 42 | @enduml 43 | -------------------------------------------------------------------------------- /docs-dev/plantuml/operation-hostmodule-sas-seqeuence.plantuml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Host-level modules SaS authentication 3 | skinparam maxMessageSize 150 4 | 5 | box Device #LightBlue 6 | participant "Your device agent" as hlm 7 | participant "Identity Service" as is 8 | participant "Keys Service" as ks 9 | end box 10 | 11 | participant "IoT Hub" as hub 12 | 13 | autonumber 14 | 15 | !startsub HOSTMODULE 16 | loop for host-level module M to create SAS token for authenticating with IoT Hub 17 | hlm -> is ++: Get identity for host module M to identify with IoT Hub 18 | is -> ks ++: Get master identity key handle 19 | return Key handle 20 | is -> ks ++: Create module derived key object for module M (based on master identity key handle) 21 | return 22 | return Module identity with derived key handle 23 | hlm -> hlm: Generate SAS token 24 | hlm -> ks++: Sign SAS token using derived key handle 25 | return Signed SAS token 26 | hlm -> hlm: Generate SharedAccessSignature for authenticating with IoT Hub 27 | hlm -> hlm: Create IoT Hub client with SAS token 28 | hlm -> hub++: Connect to IoT Hub 29 | hub -> hub: Validate SAS token against SAS key that was registered when the Edge Agent identity was created by the runtime 30 | return OK 31 | end 32 | !endsub 33 | 34 | @enduml 35 | -------------------------------------------------------------------------------- /docs-dev/running/pkcs11.md: -------------------------------------------------------------------------------- 1 | # Setting up your PKCS#11 library 2 | 3 | Follow the user steps at 4 | 5 | If you want to use tpm2-pkcs11 with the TPM simulator, see [`swtpm`](swtpm.md) 6 | 7 | To verify your HSM and its PKCS#11 library with aziot-keyd, see [Testing the openssl engine.](aziot-keyd.md#testing-the-openssl-engine) 8 | 9 | If the script mentioned there completes successfully, then the hardware and PKCS#11 library ought to be suitable for `aziot-keyd` to use. If there are errors such as crashes or signature verification failures, then it might be a problem with the hardware configuration, a bug in the PKCS#11 library, or a bug in the PKCS#11-related code in this repository. 10 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate 2 | markdown: GFM 3 | -------------------------------------------------------------------------------- /docs/_includes/nav.html: -------------------------------------------------------------------------------- 1 | 12 | 13 | 44 | -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # HTTP API of the services 2 | 3 | These pages document the HTTP API of the services, for use by host module authors. 4 | 5 | - [Identity Service](identity-service.md) 6 | 7 | - [Keys Service](keys-service.md) 8 | 9 | - [Certificates Service](certificates-service.md) 10 | -------------------------------------------------------------------------------- /docs/aziotctl.md: -------------------------------------------------------------------------------- 1 | # Managing the Azure Iot Identity Service 2 | 3 | The `aziotctl` CLI tool is used to manage and interact with the services. 4 | 5 | See `aziotctl --help` for the full help. A few notable commands are listed below. 6 | 7 | Note that most `aziotctl` commands need to be run as root. 8 | 9 | 10 | ## Applying changes in the super-config to the services 11 | 12 | ```sh 13 | sudo aziotctl config apply 14 | ``` 15 | 16 | By default, this command expects the super-config to be at `/etc/aziot/config.toml`. To use a different path, specify the `-c / --config` parameter. 17 | 18 | 19 | ## Stop all services 20 | 21 | ```sh 22 | sudo aziotctl system stop 23 | ``` 24 | 25 | 26 | ## Restart all services 27 | 28 | ```sh 29 | sudo aziotctl system restart 30 | ``` 31 | 32 | Note: Since the services use systemd socket activation, this command starts all the socket units but does not start any service except the Identity Service (`aziot-identityd.service`). The other services (`aziot-keyd.service`, `aziot-certd.service`, etc) will automatically start if they need to. 33 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuring the Azure IoT Identity Service 2 | 3 | The Azure IoT Identity Service package installs four different services - the Identity Service, Keys Service, Certificates Service, and TPM Service. All of these services can be configured from a single configuration file, called the "super-config". 4 | 5 | A template of this file is installed at `/etc/aziot/config.toml.template`. Copy it to a new file `/etc/aziot/config.toml`, and edit the file with the details of your device, IoT Hub, etc, based on the comments in the file. Then, run the command `sudo aziotctl config apply` to apply the configuration to the services. 6 | 7 | ```sh 8 | # Copy the template to a new file 9 | sudo cp /etc/aziot/config.toml.template /etc/aziot/config.toml 10 | 11 | # Edit the new empty config and fill in your provisioning information, 12 | # plus anything else you want to customize. See the comments in the file for details. 13 | sudo $EDITOR /etc/aziot/config.toml 14 | 15 | # Apply the configuration to the services 16 | sudo aziotctl config apply 17 | ``` 18 | 19 | If you need to make any changes to the `/etc/aziot/config.toml` file, do so, then re-run `sudo aziotctl config apply` to re-apply those changes to the services. 20 | -------------------------------------------------------------------------------- /docs/socket-throttling.md: -------------------------------------------------------------------------------- 1 | # Socket Throttling 2 | 3 | Each of the services' sockets implement a throttling mechanism to prevent a malicious process from making continuous requests and denying service to other processes. By default, this throttling mechanism limits each caller to making 10 simultaneous requests per socket. Each caller is identified by its UID, so two processes sharing the same UNIX user will be throttled together. 4 | 5 | If requests on a socket exceed this limit, a service will deny all further requests on its socket until the number of in-progress requests falls below 10. When a service denies a request, it closes the socket connection without sending a reply; this will be reported as an OS-level error (not an HTTP API error) to the caller. It is always the caller's responsibility to retry a request that failed due to throttling. 6 | 7 | In addition to closing the socket connection, services will also log a message. The exact message may change between versions, but it will always specify which user (UNIX UID) was throttled. 8 | 9 | ``` 10 | [INFO] Max simultaneous connections reached for user 1000 11 | ``` 12 | 13 | Note that even the services' users (i.e. `aziotks`, `aziotcs`, `aziotid`) are subject to throttling when they make a request to other services. 14 | 15 | ## Raising the throttling limit 16 | 17 | The default limit is 10 simultaneous requests per user. Should this be insufficient, a higher throttling limit can be specified in config.toml. 18 | 19 | Each service's config.toml can specifiy the `max_requests` setting. For example, to raise the throttling limit for keyd to 50, add the following to keyd's config.toml. 20 | 21 | ```toml 22 | max_requests = 50 23 | ``` 24 | 25 | The throttling limit can be specified in the super config for each service by adding the `[aziot_max_requests]`. For example: 26 | 27 | ```toml 28 | [aziot_max_requests] 29 | keyd = 20 30 | certd = 30 31 | tpmd = 40 32 | identityd = 50 33 | ``` 34 | -------------------------------------------------------------------------------- /http-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | async-trait = "0.1" 9 | base64 = "0.21" 10 | futures-util = "0.3" 11 | headers = { version = "0.3" } 12 | http = "0.2" 13 | hyper = { version = "0.14", features = ["client", "http1", "server", "stream", "tcp"] } 14 | hyper-openssl = { version = "0.9" } 15 | hyper-proxy = { version = "0.9", features = ["openssl-tls"], default-features = false } 16 | libc = "0.2" 17 | log = "0.4" 18 | nix = "0.26" 19 | openssl = { version = "0.10" } 20 | openssl-sys = { version = "0.9" } 21 | percent-encoding = "2" 22 | rand = "0.8.5" 23 | serde = { version = "1", features = ["derive"] } 24 | serde_json = "1" 25 | tokio = { version = "1", features = ["net", "rt-multi-thread", "sync", "time"] } 26 | tracing = { version = "0.1", features = ["log"] } 27 | url = { version = "2", features = ["serde"] } 28 | 29 | [dev-dependencies] 30 | aziot-identity-common = { path = "../identity/aziot-identity-common" } 31 | env_logger = "0.10" 32 | serde_json = "1" 33 | tokio = { version = "1", features = ["net", "rt", "sync", "time", "macros"] } 34 | 35 | [features] 36 | no-socket-throttle = [] 37 | -------------------------------------------------------------------------------- /http-common/src/backoff.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use std::time::Duration; 4 | 5 | use rand::Rng; 6 | 7 | pub const DEFAULT_BACKOFF: Backoff<4> = Backoff { 8 | pattern: [ 9 | BackoffInstance::from_secs(60, 10), 10 | BackoffInstance::from_secs(120, 20), 11 | BackoffInstance::from_secs(180, 30), 12 | BackoffInstance::from_secs(300, 30), 13 | ], 14 | }; 15 | 16 | pub struct Backoff { 17 | pattern: [BackoffInstance; N], 18 | } 19 | 20 | impl Backoff { 21 | #[allow(clippy::unused_self, clippy::cast_possible_truncation)] 22 | pub fn max_retries(&self) -> u32 { 23 | N as u32 24 | } 25 | 26 | /// Computes backoff for current try. Returns None if no retry attempts left 27 | pub fn get_backoff_duration(&self, current_attempt: u32) -> Option { 28 | self.pattern 29 | .get(current_attempt as usize - 1) 30 | .map(BackoffInstance::backoff_duration) 31 | } 32 | } 33 | 34 | pub struct BackoffInstance { 35 | duration: Duration, 36 | max_jitter: Duration, 37 | } 38 | 39 | impl BackoffInstance { 40 | const fn from_secs(duration: u64, max_jitter: u64) -> Self { 41 | Self { 42 | duration: Duration::from_secs(duration), 43 | max_jitter: Duration::from_secs(max_jitter), 44 | } 45 | } 46 | 47 | fn backoff_duration(&self) -> Duration { 48 | let mut rng = rand::thread_rng(); 49 | let jitter_multiple = rng.gen_range(0.0..1.0); 50 | 51 | self.duration + self.max_jitter.mul_f32(jitter_multiple) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /http-common/src/dynrange.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; 4 | 5 | /// An object-safe version of `std::ops::RangeBounds`. 6 | pub trait DynRangeBounds 7 | where 8 | T: std::cmp::PartialOrd, 9 | { 10 | fn contains(&self, item: &T) -> bool; 11 | } 12 | 13 | impl DynRangeBounds for Box> 14 | where 15 | T: std::cmp::PartialOrd, 16 | { 17 | fn contains(&self, item: &T) -> bool { 18 | (**self).contains(item) 19 | } 20 | } 21 | 22 | macro_rules! impl_dynrange { 23 | ($($range:ident),*) => {$( 24 | impl DynRangeBounds for $range 25 | where T: std::cmp::PartialOrd 26 | { 27 | fn contains(&self, item: &T) -> bool { 28 | $range::contains(self, item) 29 | } 30 | } 31 | )*}; 32 | } 33 | 34 | impl_dynrange!(Range, RangeFrom, RangeTo, RangeToInclusive, RangeInclusive); 35 | 36 | // RangeFull doesn't have a generic parameter associated with it. 37 | impl DynRangeBounds for RangeFull 38 | where 39 | T: std::cmp::PartialOrd, 40 | { 41 | fn contains(&self, _item: &T) -> bool { 42 | true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /http-common/src/uid.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use libc::{pid_t, uid_t}; 4 | 5 | pub struct UidService { 6 | pid: Option, 7 | uid: uid_t, 8 | inner: T, 9 | } 10 | 11 | impl UidService { 12 | pub fn new(pid: Option, uid: uid_t, inner: T) -> Self { 13 | UidService { pid, uid, inner } 14 | } 15 | } 16 | 17 | impl hyper::service::Service> for UidService 18 | where 19 | T: hyper::service::Service< 20 | hyper::Request, 21 | Response = hyper::Response, 22 | Error = std::convert::Infallible, 23 | >, 24 | >>::Future: Send + 'static, 25 | { 26 | type Response = T::Response; 27 | type Error = std::convert::Infallible; 28 | type Future = std::pin::Pin< 29 | Box< 30 | dyn std::future::Future< 31 | Output = Result, std::convert::Infallible>, 32 | > + Send, 33 | >, 34 | >; 35 | 36 | fn call(&mut self, req: hyper::Request) -> Self::Future { 37 | let mut req = req; 38 | let extensions = req.extensions_mut(); 39 | extensions.insert(self.uid); 40 | extensions.insert(self.pid); 41 | Box::pin(self.inner.call(req)) 42 | } 43 | 44 | fn poll_ready( 45 | &mut self, 46 | _cx: &mut std::task::Context<'_>, 47 | ) -> std::task::Poll> { 48 | std::task::Poll::Ready(Ok(())) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /identity/aziot-cloud-client-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-cloud-client-async" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | publish = false 7 | 8 | [dependencies] 9 | async-trait = "0.1" 10 | base64 = "0.21" 11 | chrono = "0.4" 12 | hyper = "0.14" 13 | hyper-openssl = "0.9" 14 | log = "0.4" 15 | percent-encoding = "2" 16 | serde = "1" 17 | serde_json = "1" 18 | tokio = { version = "1", features = ["parking_lot", "time"] } 19 | url = "2" 20 | 21 | aziot-identity-common = { path = "../aziot-identity-common" } 22 | aziot-key-client-async = { path = "../../key/aziot-key-client-async" } 23 | aziot-key-common = { path = "../../key/aziot-key-common" } 24 | aziot-tpm-client-async = { path = "../../tpm/aziot-tpm-client-async" } 25 | aziot-tpm-common = { path = "../../tpm/aziot-tpm-common" } 26 | 27 | http-common = { path = "../../http-common" } 28 | -------------------------------------------------------------------------------- /identity/aziot-cloud-client-async/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)] 6 | 7 | mod connector; 8 | 9 | pub mod dps; 10 | pub use dps::schema::request as DpsRequest; 11 | pub use dps::schema::response as DpsResponse; 12 | pub use dps::Client as DpsClient; 13 | 14 | pub mod hub; 15 | pub use hub::Client as HubClient; 16 | 17 | type KeyClient = std::sync::Arc; 18 | type TpmClient = std::sync::Arc; 19 | 20 | type CloudConnector = 21 | http_common::MaybeProxyConnector>; 22 | 23 | const ENCODE_SET: &percent_encoding::AsciiSet = &http_common::PATH_SEGMENT_ENCODE_SET.add(b'='); 24 | -------------------------------------------------------------------------------- /identity/aziot-identity-client-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-identity-client-async" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | http = "0.2" 9 | hyper = "0.14" 10 | percent-encoding = "2" 11 | 12 | aziot-cert-common-http = { path = "../../cert/aziot-cert-common-http" } 13 | aziot-identity-common = { path = "../aziot-identity-common" } 14 | aziot-identity-common-http = { path = "../aziot-identity-common-http" } 15 | http-common = { path = "../../http-common" } 16 | -------------------------------------------------------------------------------- /identity/aziot-identity-common-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-identity-common-http" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | serde = { version = "1", features = ["derive"] } 11 | serde_json = "1" 12 | 13 | aziot-cert-common-http = { path = "../../cert/aziot-cert-common-http" } 14 | aziot-identity-common = { path = "../aziot-identity-common" } 15 | aziot-key-common = { path = "../../key/aziot-key-common" } 16 | http-common = { path = "../../http-common" } 17 | -------------------------------------------------------------------------------- /identity/aziot-identity-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-identity-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | openssl = "0.10" 11 | serde = { version = "1", features = ["derive"] } 12 | 13 | aziot-key-common = { path = "../../key/aziot-key-common" } 14 | http-common = { path = "../../http-common" } 15 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-identityd-config" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | publish = false 6 | description = """ 7 | The code used for Identity Service. 8 | """ 9 | edition = "2021" 10 | 11 | 12 | [dependencies] 13 | libc = "0.2" 14 | openssl = "0.10" 15 | serde = { version = "1", features = ["derive"] } 16 | serde_json = "1" 17 | url = { version = "2", features = ["serde"] } 18 | 19 | aziot-identity-common = { path = "../aziot-identity-common" } 20 | cert-renewal = { path = "../../cert/cert-renewal"} 21 | http-common = { path = "../../http-common" } 22 | 23 | [dev-dependencies] 24 | toml = "0.7" 25 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/complex_payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "model_id": "ACME 2000", 3 | "cpuinfo": [ 4 | { 5 | "cache size": "8192 KB", 6 | "cpu MHz": 2112.007, 7 | "processor": 0 8 | }, 9 | { 10 | "cache size": "8192 KB", 11 | "cpu MHz": 2112.007, 12 | "processor": 1 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/good_dps_config.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [provisioning] 8 | source = "dps" 9 | "global_endpoint" = "http://globaldevices.net" 10 | "scope_id" = "scope" 11 | 12 | [provisioning.attestation] 13 | method = "symmetric_key" 14 | registration_id = "regid" 15 | symmetric_key = "dps" 16 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/good_dps_config_with_complex_payload.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [provisioning] 8 | source = "dps" 9 | "global_endpoint" = "http://globaldevices.net" 10 | "scope_id" = "scope" 11 | payload = { uri = "file:///tmp/complex_payload.json" } 12 | 13 | [provisioning.attestation] 14 | method = "symmetric_key" 15 | registration_id = "regid" 16 | symmetric_key = "dps" 17 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/good_dps_config_with_simple_payload.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [provisioning] 8 | source = "dps" 9 | "global_endpoint" = "http://globaldevices.net" 10 | "scope_id" = "scope" 11 | payload = { uri = "file:///tmp/simple_payload.json" } 12 | 13 | [provisioning.attestation] 14 | method = "symmetric_key" 15 | registration_id = "regid" 16 | symmetric_key = "dps" 17 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/good_sas_config.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [provisioning] 8 | source = "manual" 9 | iothub_hostname = "hubname" 10 | device_id = "deviceid" 11 | 12 | [provisioning.authentication] 13 | method = "sas" 14 | device_id_pk = "sas" 15 | -------------------------------------------------------------------------------- /identity/aziot-identityd-config/test/simple_payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "model_id": "ACME 2000" 3 | } -------------------------------------------------------------------------------- /identity/aziot-identityd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-identityd" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | publish = false 6 | description = """ 7 | The code used for Identity Service. 8 | """ 9 | edition = "2021" 10 | 11 | 12 | [dependencies] 13 | async-trait = "0.1" 14 | chrono = "0.4" 15 | futures-util = "0.3" 16 | hex = "0.4" 17 | http = "0.2" 18 | hyper = "0.14" 19 | lazy_static = "1" 20 | libc = "0.2" 21 | log = "0.4" 22 | openssl = "0.10" 23 | openssl-sys = "0.9" 24 | percent-encoding = "2" 25 | regex = "1" 26 | serde = "1" 27 | serde_json = "1.0" 28 | tokio = { version = "1", features = ["parking_lot", "time"] } 29 | toml = "0.7" 30 | url = "2" 31 | 32 | aziot-cert-client-async = { path = "../../cert/aziot-cert-client-async" } 33 | aziot-cert-common-http = { path = "../../cert/aziot-cert-common-http" } 34 | aziot-cloud-client-async = { path = "../aziot-cloud-client-async" } 35 | aziot-identity-common = { path = "../aziot-identity-common" } 36 | aziot-identity-common-http = { path = "../aziot-identity-common-http" } 37 | aziot-identityd-config = { path = "../aziot-identityd-config" } 38 | aziot-key-client = { path = "../../key/aziot-key-client" } 39 | aziot-key-client-async = { path = "../../key/aziot-key-client-async" } 40 | aziot-key-common = { path = "../../key/aziot-key-common" } 41 | aziot-key-common-http = { path = "../../key/aziot-key-common-http" } 42 | aziot-key-openssl-engine = { path = "../../key/aziot-key-openssl-engine" } 43 | aziot-tpm-client-async = { path = "../../tpm/aziot-tpm-client-async" } 44 | aziot-tpm-common-http = { path = "../../tpm/aziot-tpm-common-http" } 45 | 46 | cert-renewal = { path = "../../cert/cert-renewal" } 47 | config-common = { path = "../../config-common", features = ["watcher"] } 48 | http-common = { path = "../../http-common" } 49 | openssl2 = { path = "../../openssl2" } 50 | 51 | [build-dependencies] 52 | openssl-build = { path = "../../openssl-build/" } 53 | 54 | [dev-dependencies] 55 | -------------------------------------------------------------------------------- /identity/aziot-identityd/aziot-identityd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Identity Service 3 | Requires=aziot-identityd.socket 4 | After=aziot-identityd.socket 5 | 6 | [Service] 7 | Environment="LD_LIBRARY_PATH=@private-libs@" 8 | ExecStart=@libexecdir@/aziot-identity-service/aziot-identityd 9 | KillMode=process 10 | Restart=on-failure 11 | RestartSec=5s 12 | User=@user_aziotid@ 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /identity/aziot-identityd/aziot-identityd.socket.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Identity Service API socket 3 | PartOf=aziot-identityd.service 4 | 5 | [Socket] 6 | ListenStream=@socket_dir@/identityd.sock 7 | SocketMode=0660 8 | DirectoryMode=0755 9 | SocketUser=@user_aziotid@ 10 | SocketGroup=@user_aziotid@ 11 | 12 | [Install] 13 | WantedBy=sockets.target 14 | -------------------------------------------------------------------------------- /identity/aziot-identityd/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | openssl_build::define_version_number_cfg(); 8 | } 9 | -------------------------------------------------------------------------------- /identity/aziot-identityd/config/unix/default.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | # Identity service configuration used to associate provisioned device and module identities to host-level processes. 8 | # This configuration will also be used to generate new module identities, if not created in Azure IoT Hub already. 9 | # [[principal]] 10 | # name = "hostdaemon1" 11 | # uid = 1001 12 | 13 | # [[principal]] 14 | # name = "hostprocess1" 15 | # idtype = "device" 16 | # uid = 1002 17 | 18 | # [[principal]] 19 | # name = "hostprocess2" 20 | # idtype = "module" 21 | # uid = 1003 22 | 23 | 24 | # [provisioning] 25 | # source = "manual" 26 | # iothub_hostname = "hubname" 27 | # device_id = "deviceid" 28 | 29 | # [provisioning.authentication] 30 | # method = "sas" 31 | # device_id_pk = "device-id" 32 | 33 | # [provisioning.authentication] 34 | # method = "x509" 35 | # iothub_hostname = "hubname" 36 | # device_id = "deviceid" 37 | # device_id_cert = "device-id" 38 | # device_id_pk = "device-id" 39 | 40 | # [provisioning] 41 | # "source" = "dps" 42 | # "global_endpoint" = "https://global.azure-devices-provisioning.net/" 43 | # "scope_id" = "" 44 | 45 | # [provisioning.attestation] 46 | # "method" = "symmetric_key" 47 | # "registration_id" = "" 48 | # "symmetric_key" = "device-id" #Pre-loaded Key service handle 49 | # 50 | # [provisioning.attestation] 51 | # "method" = "x509" 52 | # "identity_cert" = "device-id" 53 | # "identity_pk" = "device-id" 54 | 55 | 56 | # EST provisioning case 57 | # [provisioning] 58 | # "source" = "dps" 59 | # "scope_id" = "" 60 | 61 | # [provisioning.attestation] 62 | # "method" = "x509" 63 | # "identity_cert" = "est" 64 | # "identity_pk" = "est" 65 | -------------------------------------------------------------------------------- /identity/aziot-identityd/src/auth/authorization.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use crate::auth::Operation; 4 | use crate::error::Error; 5 | 6 | /// A trait to authenticate IS clients with given user id. 7 | pub trait Authorizer { 8 | /// Authentication error. 9 | type Error: std::error::Error + Send; 10 | 11 | /// Authorizes an IS operation to be performed. 12 | fn authorize(&self, operation: Operation) -> Result; 13 | } 14 | 15 | impl Authorizer for F 16 | where 17 | F: Fn(Operation) -> Result + Send + Sync, 18 | { 19 | type Error = Error; 20 | 21 | fn authorize(&self, operation: Operation) -> Result { 22 | self(operation) 23 | } 24 | } 25 | 26 | // Default implementation that rejects any operation by default. 27 | pub struct DefaultAuthorizer; 28 | 29 | impl Authorizer for DefaultAuthorizer { 30 | type Error = Error; 31 | 32 | fn authorize(&self, _: Operation) -> Result { 33 | Ok(false) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use crate::auth::authorization::Authorizer; 40 | use crate::auth::{AuthId, Operation, OperationType}; 41 | 42 | #[test] 43 | fn authorizer_wrapper_around_function() { 44 | let auth = |_| Ok(true); 45 | let operation = Operation { 46 | auth_id: AuthId::Unknown, 47 | op_type: OperationType::GetDevice, 48 | }; 49 | 50 | let res = auth.authorize(operation); 51 | 52 | match res { 53 | Ok(true) => (), 54 | _ => panic!("incorrect authorization returned"), 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /identity/aziot-identityd/src/auth/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![allow(clippy::module_name_repetitions)] 4 | 5 | pub mod authentication; 6 | pub mod authorization; 7 | 8 | /// Authenticated user types 9 | #[derive(Clone, Eq, PartialEq, PartialOrd)] 10 | pub enum AuthId { 11 | Unknown, 12 | 13 | HostProcess(aziot_identityd_config::Principal), 14 | 15 | Daemon, 16 | 17 | LocalRoot, 18 | } 19 | 20 | /// Operation types to be authorized 21 | #[derive(Clone, Eq, PartialEq, PartialOrd)] 22 | pub enum OperationType { 23 | GetModule(String), 24 | GetAllHubModules, 25 | GetDevice, 26 | CreateModule(String), 27 | DeleteModule(String), 28 | UpdateModule(String), 29 | ReprovisionDevice, 30 | GetTrustBundle, 31 | } 32 | 33 | /// Operation to be authorized 34 | pub struct Operation { 35 | pub auth_id: AuthId, 36 | 37 | pub op_type: OperationType, 38 | } 39 | -------------------------------------------------------------------------------- /identity/aziot-identityd/src/http/get_provisioning_info.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | pub(super) struct Route { 4 | api: std::sync::Arc>, 5 | } 6 | 7 | #[async_trait::async_trait] 8 | impl http_common::server::Route for Route { 9 | type ApiVersion = aziot_identity_common_http::ApiVersion; 10 | fn api_version() -> &'static dyn http_common::DynRangeBounds { 11 | &((aziot_identity_common_http::ApiVersion::V2021_12_01)..) 12 | } 13 | 14 | type Service = super::Service; 15 | fn from_uri( 16 | service: &Self::Service, 17 | path: &str, 18 | _query: &[(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)], 19 | _extensions: &http::Extensions, 20 | ) -> Option { 21 | if path != "/identities/provisioning" { 22 | return None; 23 | } 24 | 25 | Some(Route { 26 | api: service.api.clone(), 27 | }) 28 | } 29 | 30 | async fn get(self) -> http_common::server::RouteResponse { 31 | let api = self.api.lock().await; 32 | let provisioning = api 33 | .get_provisioning_info() 34 | .await 35 | .map_err(|err| super::to_http_error(&err))?; 36 | 37 | let res = http_common::server::response::json(hyper::StatusCode::OK, &provisioning); 38 | Ok(res) 39 | } 40 | 41 | type DeleteBody = serde::de::IgnoredAny; 42 | type PostBody = serde::de::IgnoredAny; 43 | type PutBody = serde::de::IgnoredAny; 44 | } 45 | -------------------------------------------------------------------------------- /identity/aziot-identityd/test/bad_config.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [connect] 8 | api_uri = "unix:///run/aziot/identityd.sock" 9 | 10 | [listen] 11 | api_uri = "unix:///run/aziot/identityd.sock" 12 | 13 | [provisioning] 14 | source = "dps2" #Incorrect source type 15 | "global_endpoint" = "http://globaldevices.net" 16 | "scope_id" = "scope" 17 | 18 | [provisioning.attestation] 19 | method = "symmetric_key" 20 | registration_id = "regid" 21 | symmetric_key = "dps" 22 | -------------------------------------------------------------------------------- /identity/aziot-identityd/test/bad_local_config.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [connect] 8 | api_uri = "unix:///run/aziot/identityd.sock" 9 | 10 | [listen] 11 | api_uri = "unix:///run/aziot/identityd.sock" 12 | 13 | [provisioning] 14 | source = "dps" 15 | "global_endpoint" = "http://globaldevices.net" 16 | "scope_id" = "scope" 17 | 18 | # Principal specifies local id, but [localid] not in settings. 19 | [[principal]] 20 | uid = 1001 21 | name = "hostdaemon1" 22 | idtype = ["local"] 23 | 24 | [provisioning.attestation] 25 | method = "symmetric_key" 26 | registration_id = "regid" 27 | symmetric_key = "dps" 28 | -------------------------------------------------------------------------------- /identity/aziot-identityd/test/good_auth_settings.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | # Local ID settings 8 | [localid] 9 | domain = "example.com" 10 | 11 | # Identity service configuration used to associate provisioned device and module identities to host-level processes. 12 | # This configuration will also be used to generate new module identities, if not created in Azure IoT Hub already. 13 | [[principal]] 14 | name = "hostdaemon1" 15 | uid = 1001 16 | 17 | [[principal]] 18 | name = "hostprocess1" 19 | idtype = ["device"] 20 | uid = 1002 21 | 22 | [[principal]] 23 | name = "hostprocess2" 24 | idtype = ["module", "local"] 25 | uid = 1003 26 | 27 | [provisioning] 28 | source = "manual" 29 | iothub_hostname = "hubname" 30 | device_id = "deviceid" 31 | 32 | [provisioning.authentication] 33 | method = "sas" 34 | device_id_pk = "sas" 35 | 36 | # [provisioning] 37 | # "source" = "dps" 38 | # "global_endpoint" = "http://globaldevices.net" 39 | # "scope_id" = "" 40 | 41 | # [provisioning.attestation] 42 | # "method" = "symmetric_key" 43 | # "registration_id" = "" 44 | # "symmetric_key" = "dps" #Pre-loaded Key service handle 45 | # 46 | # [provisioning.attestation] 47 | # "method" = "x509" 48 | # "identity_cert" = "device-id" 49 | # "identity_pk" = "device-id" 50 | 51 | 52 | # EST provisioning case 53 | # [provisioning] 54 | # "source" = "dps" 55 | # "scope_id" = "" 56 | 57 | # [provisioning.attestation] 58 | # "method" = "x509" 59 | # "identity_cert" = "est" 60 | # "identity_pk" = "est" 61 | -------------------------------------------------------------------------------- /identity/aziot-identityd/test/good_local_opts.toml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Identity Service configuration 3 | ############################################################################### 4 | hostname = "iotedge" 5 | homedir = "/var/lib/aziot/identityd" 6 | 7 | [connect] 8 | api_uri = "unix:///var/run/aziot/identityd.sock" 9 | 10 | [listen] 11 | api_uri = "unix:///var/run/aziot/identityd.sock" 12 | 13 | [endpoints] 14 | aziot_certd = "unix:///var/run/aziot/certd.sock" 15 | aziot_keyd = "unix:///var/run/aziot/keyd.sock" 16 | aziot_identityd = "unix:///var/run/aziot/identityd.sock" 17 | aziot_tpmd = "unix:///var/run/aziot/tpmd.sock" 18 | 19 | [provisioning] 20 | source = "none" 21 | 22 | [localid] 23 | domain = "example.com" 24 | 25 | [[principal]] 26 | uid = 1000 27 | name = "module1" 28 | idtype = ["local"] 29 | 30 | [[principal]] 31 | uid = 1001 32 | name = "module2" 33 | idtype = ["local"] 34 | localid = { type = "x509" } 35 | 36 | [[principal]] 37 | uid = 1002 38 | name = "module3" 39 | idtype = ["local"] 40 | localid = { type = "x509", attributes = "server" } 41 | -------------------------------------------------------------------------------- /identity/mock-iot-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mock-iot-server" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | chrono = "0.4" 9 | clap = { version = "4", features = ["derive"] } 10 | http = "0.2" 11 | hyper = { version = "0.14", features = ["http1", "server"] } 12 | lazy_static = "1.4" 13 | openssl = "0.10" 14 | percent-encoding = "2" 15 | regex = "1" 16 | serde = "1" 17 | serde_json = "1" 18 | tokio = { version = "1", features = ["macros", "net", "rt-multi-thread"] } 19 | tokio-openssl = "0.6" 20 | uuid = { version = "1", features = ["v4"] } 21 | 22 | aziot-cloud-client-async = { path = "../aziot-cloud-client-async" } 23 | aziot-identity-common = { path = "../aziot-identity-common" } 24 | test-common = { path = "../../test-common" } 25 | -------------------------------------------------------------------------------- /identity/mock-iot-server/README.md: -------------------------------------------------------------------------------- 1 | # mock-iot-server 2 | 3 | mock-iot-server provides a subset of DPS server and IoT Hub functionality for testing. In its current form, it is *not* a substitute for testing with a real DPS or IoT Hub. 4 | - Does not verify any client credentials 5 | - May return the same hardcoded responses to all clients 6 | - May panic on error 7 | 8 | ## Arguments 9 | 10 | Required arguments: 11 | - `--port`: Port to listen on. Hostname is always `localhost`. 12 | - `--server-cert-chain`: Path to server cert chain, starting with the leaf and ending with the root. 13 | - `--server-key`: Server cert key. 14 | 15 | ## TLS server certificate 16 | 17 | Since Azure only accepts requests over TLS, mock-iot-server needs a TLS server certificate. See [mock-iot-cert-gen.sh](../../ci/mock-iot-tests/mock-iot-cert-gen.sh) for an example on how to generate a root CA certificate and TLS server certificate for mock-iot-server. 18 | 19 | mock-iot-server's root CA certificate must be installed to the system's root CA certificate store. 20 | -------------------------------------------------------------------------------- /identity/mock-iot-server/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | mod dps; 7 | mod hub; 8 | mod server; 9 | 10 | use clap::Parser; 11 | 12 | #[derive(Parser)] 13 | struct Options { 14 | #[arg(long)] 15 | port: u16, 16 | 17 | #[arg(long)] 18 | server_cert_chain: std::path::PathBuf, 19 | 20 | #[arg(long)] 21 | server_key: std::path::PathBuf, 22 | } 23 | 24 | #[tokio::main] 25 | async fn main() { 26 | let options = Options::parse(); 27 | 28 | println!( 29 | "Using server certificate chain {}", 30 | options.server_cert_chain.to_str().unwrap() 31 | ); 32 | println!( 33 | "Using server private key {}", 34 | options.server_key.to_str().unwrap() 35 | ); 36 | 37 | let server_key = std::fs::read_to_string(&options.server_key).unwrap(); 38 | let server_key = openssl::pkey::PKey::private_key_from_pem(server_key.as_bytes()).unwrap(); 39 | 40 | let server_context = crate::server::ContextInner::new(&options); 41 | let server_context = std::sync::Mutex::new(server_context); 42 | let server_context = std::sync::Arc::new(server_context); 43 | 44 | println!("Listening on localhost:{}.", options.port); 45 | let incoming = test_common::tokio_openssl2::Incoming::new( 46 | "localhost", 47 | options.port, 48 | &options.server_cert_chain, 49 | &server_key, 50 | false, 51 | ) 52 | .unwrap(); 53 | 54 | let server = 55 | hyper::Server::builder(incoming).serve(hyper::service::make_service_fn(move |_| { 56 | let context = server_context.clone(); 57 | 58 | let service = hyper::service::service_fn(move |req| { 59 | crate::server::serve_request(context.clone(), req) 60 | }); 61 | 62 | async move { Ok::<_, std::convert::Infallible>(service) } 63 | })); 64 | 65 | server.await.unwrap(); 66 | } 67 | -------------------------------------------------------------------------------- /key/aziot-key-client-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-client-async" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | http = "0.2" 9 | hyper = "0.14" 10 | percent-encoding = "2" 11 | 12 | http-common = { path = "../../http-common" } 13 | aziot-key-common = { path = "../aziot-key-common" } 14 | aziot-key-common-http = { path = "../aziot-key-common-http" } 15 | -------------------------------------------------------------------------------- /key/aziot-key-client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-client" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | http = "0.2" 9 | httparse = "1" 10 | percent-encoding = "2" 11 | serde = "1" 12 | serde_json = "1" 13 | 14 | aziot-key-common = { path = "../aziot-key-common" } 15 | aziot-key-common-http = { path = "../aziot-key-common-http" } 16 | http-common = { path = "../../http-common" } 17 | -------------------------------------------------------------------------------- /key/aziot-key-common-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-common-http" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | serde = { version = "1", features = ["derive"] } 9 | 10 | aziot-key-common = { path = "../aziot-key-common" } 11 | http-common = { path = "../../http-common" } 12 | -------------------------------------------------------------------------------- /key/aziot-key-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | serde = { version = "1", features = ["derive"] } 9 | -------------------------------------------------------------------------------- /key/aziot-key-common/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 7 | pub struct KeyHandle(pub String); 8 | 9 | #[derive(Clone, Debug)] 10 | pub enum CreateKeyValue { 11 | Generate, 12 | Import { bytes: Vec }, 13 | } 14 | 15 | #[derive(Clone, Copy, Debug)] 16 | pub enum KeyUsage { 17 | Derive, 18 | Encrypt, 19 | Sign, 20 | } 21 | 22 | #[derive(Clone, Copy, Debug)] 23 | pub enum SignMechanism { 24 | // ECDSA keys 25 | Ecdsa, 26 | 27 | // Symmetric keys 28 | HmacSha256, 29 | } 30 | 31 | #[derive(Clone, Debug)] 32 | pub enum EncryptMechanism { 33 | /// AEAD mechanism, like AES-GCM. 34 | Aead { iv: Vec, aad: Vec }, 35 | 36 | /// RSA with PKCS1 padding. 37 | RsaPkcs1, 38 | 39 | /// RSA with no padding. Padding will have been performed by the caller. 40 | RsaNoPadding, 41 | } 42 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine-shared-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-openssl-engine-shared-test" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | 8 | 9 | [dependencies] 10 | backtrace = "0.3" 11 | clap = { version = "4", features = ["derive"] } 12 | futures-util = "0.3" 13 | http = "0.2" 14 | hyper = { version = "0.14", features = ["client", "http1"] } 15 | hyper-openssl = "0.9" 16 | openssl = "0.10" 17 | tokio = { version = "1", features = ["macros", "rt-multi-thread"] } 18 | 19 | openssl2 = { path = "../../openssl2/" } 20 | openssl-sys2 = { path = "../../openssl-sys2/" } 21 | 22 | test-common = { path = "../../test-common" } 23 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine-shared/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-openssl-engine-shared" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Arnav Singh "] 6 | edition = "2021" 7 | build = "build/main.rs" 8 | 9 | 10 | [lib] 11 | crate-type = ["cdylib"] 12 | 13 | 14 | [dependencies] 15 | openssl-errors = "0.2" 16 | openssl-sys = "0.9" 17 | url = "2" 18 | 19 | aziot-key-client = { path = "../aziot-key-client" } 20 | aziot-key-common-http = { path = "../aziot-key-common-http" } 21 | aziot-key-openssl-engine = { path = "../aziot-key-openssl-engine" } 22 | http-common = { path = "../../http-common" } 23 | openssl-sys2 = { path = "../../openssl-sys2" } 24 | 25 | 26 | [build-dependencies] 27 | openssl-build = { path = "../../openssl-build" } 28 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine-shared/build/engine.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft. All rights reserved. */ 2 | 3 | #include 4 | 5 | int aziot_key_openssl_engine_shared_bind(ENGINE* e, const char* id); 6 | 7 | /** 8 | * The openssl engine API uses two macros - IMPLEMENT_DYNAMIC_BIND_FN and IMPLEMENT_DYNAMIC_CHECK_FN - to register the engine's entrypoint. 9 | * 10 | * The underlying bind function that the macros expand to are not stable across openssl versions, so it's not easy to invoke them directly from Rust. 11 | * Therefore we use the macros in this C file. 12 | * 13 | * There is one more problem however. When compiling the cdylib, rustc uses a version script that only lists globals that rustc knows about. 14 | * So the bind_engine and v_check functions generated by these two macros will not actually be exported by the final cdylib. It's not possible 15 | * to provide a custom version script via `cargo:rustc-cdylib-link-arg` because it conflicts with the one generated by rustc. 16 | * 17 | * So we have to use the other way mentioned by `ld`'s docs[1], `__asm__(".symver")`. We also need to add `__attribute__((used))` since otherwise 18 | * the versioned symbol is optimized out by LTO. 19 | * 20 | * Unfortunately this trick means this crate cannot be compiled for tests since the linker will see duplicate symbols, so every invocation of 21 | * `cargo test --all` or `cargo clippy --tests --all` has to also exclude this crate with `--exclude`. When all of our platforms provide 22 | * GNU as >= 2.35 and/or Clang >= 13, we can lift this restriction by appending `,remove` to the `.symver` directive arguments[2]. 23 | * 24 | * [1]: https://sourceware.org/binutils/docs/ld/VERSION.html 25 | * [2]: https://maskray.me/blog/2020-11-26-all-about-symbol-versioning 26 | */ 27 | __attribute__((used)) 28 | IMPLEMENT_DYNAMIC_BIND_FN(aziot_key_openssl_engine_shared_bind); 29 | __asm__(".symver bind_engine,bind_engine@@"); 30 | __attribute__((used)) 31 | IMPLEMENT_DYNAMIC_CHECK_FN(); 32 | __asm__(".symver v_check,v_check@@"); 33 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine-shared/build/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | println!("cargo:rerun-if-changed=build/"); 8 | 9 | openssl_build::define_version_number_cfg(); 10 | 11 | let mut build = openssl_build::get_c_compiler(); 12 | build 13 | // Since we are going to use the generated archive in a shared 14 | // library, we need +whole-archive to be set. See: 15 | // https://github.com/rust-lang/rust/blob/1.61.0/RELEASES.md#compatibility-notes 16 | .link_lib_modifier("+whole-archive") 17 | .file("build/engine.c") 18 | .compile("aziot_key_openssl_shared_engine_wrapper"); 19 | } 20 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-key-openssl-engine" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | build = "build/main.rs" 8 | 9 | 10 | [dependencies] 11 | base64 = "0.21" 12 | foreign-types-shared = "0.1" 13 | log = "0.4" 14 | openssl = "0.10" 15 | openssl-errors = "0.2" 16 | openssl-sys = "0.9" 17 | 18 | aziot-key-client = { path = "../aziot-key-client" } 19 | aziot-key-common = { path = "../aziot-key-common" } 20 | openssl2 = { path = "../../openssl2" } 21 | openssl-sys2 = { path = "../../openssl-sys2" } 22 | 23 | 24 | [build-dependencies] 25 | openssl-build = { path = "../../openssl-build" } 26 | -------------------------------------------------------------------------------- /key/aziot-key-openssl-engine/build/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | openssl_build::define_version_number_cfg(); 8 | 9 | let mut build = openssl_build::get_c_compiler(); 10 | build 11 | .file("build/engine.c") 12 | .compile("aziot_key_openssl_engine_wrapper"); 13 | } 14 | -------------------------------------------------------------------------------- /key/aziot-keyd-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-keyd-config" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | libc = "0.2" 10 | serde = { version = "1", features = ["derive"] } 11 | 12 | http-common = { path = "../../http-common" } 13 | 14 | [dev-dependencies] 15 | toml = "0.7" 16 | -------------------------------------------------------------------------------- /key/aziot-keyd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-keyd" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | async-trait = "0.1" 10 | base64 = "0.21" 11 | futures-util = "0.3" 12 | http = "0.2" 13 | hyper = "0.14" 14 | lazy_static = "1" 15 | libc = "0.2" 16 | log = "0.4" 17 | openssl = "0.10" 18 | openssl-sys = "0.9" 19 | percent-encoding = "2" 20 | regex = "1" 21 | serde = "1" 22 | serde_json = "1" 23 | tokio = { version = "1", features = ["parking_lot", "time"] } 24 | url = "2" 25 | wildmatch = "2" 26 | 27 | aziot-key-common = { path = "../aziot-key-common" } 28 | aziot-key-common-http = { path = "../aziot-key-common-http" } 29 | aziot-keyd-config = { path = "../aziot-keyd-config" } 30 | config-common = { path = "../../config-common", features = ["watcher"] } 31 | http-common = { path = "../../http-common" } 32 | -------------------------------------------------------------------------------- /key/aziot-keyd/aziot-keyd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Keys Service 3 | Requires=aziot-keyd.socket 4 | After=aziot-keyd.socket 5 | 6 | [Service] 7 | Environment="LD_LIBRARY_PATH=@private-libs@" 8 | ExecStart=@libexecdir@/aziot-identity-service/aziot-keyd 9 | KillMode=process 10 | Restart=on-failure 11 | RestartSec=5s 12 | User=@user_aziotks@ 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /key/aziot-keyd/aziot-keyd.socket.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT Keys Service API socket 3 | PartOf=aziot-keyd.service 4 | 5 | [Socket] 6 | ListenStream=@socket_dir@/keyd.sock 7 | SocketMode=0660 8 | DirectoryMode=0755 9 | SocketUser=@user_aziotks@ 10 | SocketGroup=@user_aziotks@ 11 | 12 | [Install] 13 | WantedBy=sockets.target 14 | -------------------------------------------------------------------------------- /key/aziot-keyd/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | println!("cargo:rustc-link-lib=aziot_keys"); 8 | } 9 | -------------------------------------------------------------------------------- /key/aziot-keyd/config/unix/default.toml: -------------------------------------------------------------------------------- 1 | [aziot_keys] 2 | homedir_path = "/var/lib/aziot/keyd" 3 | # pkcs11_lib_path = "..." 4 | # pkcs11_base_slot = "..." 5 | 6 | # [preloaded_keys] 7 | -------------------------------------------------------------------------------- /key/aziot-keyd/src/http/create_derived_key.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | pub(super) struct Route { 4 | api: std::sync::Arc>, 5 | } 6 | 7 | #[async_trait::async_trait] 8 | impl http_common::server::Route for Route { 9 | type ApiVersion = aziot_key_common_http::ApiVersion; 10 | fn api_version() -> &'static dyn http_common::DynRangeBounds { 11 | &((aziot_key_common_http::ApiVersion::V2020_09_01)..) 12 | } 13 | 14 | type Service = super::Service; 15 | fn from_uri( 16 | service: &Self::Service, 17 | path: &str, 18 | _query: &[(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)], 19 | _extensions: &http::Extensions, 20 | ) -> Option { 21 | if path != "/derivedkey" { 22 | return None; 23 | } 24 | 25 | Some(Route { 26 | api: service.api.clone(), 27 | }) 28 | } 29 | 30 | type DeleteBody = serde::de::IgnoredAny; 31 | 32 | type PostBody = aziot_key_common_http::create_derived_key::Request; 33 | async fn post(self, body: Option) -> http_common::server::RouteResponse { 34 | let body = body.ok_or_else(|| http_common::server::Error { 35 | status_code: http::StatusCode::BAD_REQUEST, 36 | message: "missing request body".into(), 37 | })?; 38 | 39 | let mut api = self.api.lock().await; 40 | let api = &mut *api; 41 | 42 | let handle = match api.create_derived_key(&body.base_handle, &body.derivation_data.0) { 43 | Ok(handle) => handle, 44 | Err(err) => return Err(super::to_http_error(&err)), 45 | }; 46 | 47 | let res = aziot_key_common_http::create_derived_key::Response { handle }; 48 | let res = http_common::server::response::json(hyper::StatusCode::OK, &res); 49 | Ok(res) 50 | } 51 | 52 | type PutBody = serde::de::IgnoredAny; 53 | } 54 | -------------------------------------------------------------------------------- /key/aziot-keyd/src/http/export_derived_key.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | pub(super) struct Route { 4 | api: std::sync::Arc>, 5 | } 6 | 7 | #[async_trait::async_trait] 8 | impl http_common::server::Route for Route { 9 | type ApiVersion = aziot_key_common_http::ApiVersion; 10 | fn api_version() -> &'static dyn http_common::DynRangeBounds { 11 | &((aziot_key_common_http::ApiVersion::V2020_09_01)..) 12 | } 13 | 14 | type Service = super::Service; 15 | fn from_uri( 16 | service: &Self::Service, 17 | path: &str, 18 | _query: &[(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)], 19 | _extensions: &http::Extensions, 20 | ) -> Option { 21 | if path != "/derivedkey/export" { 22 | return None; 23 | } 24 | 25 | Some(Route { 26 | api: service.api.clone(), 27 | }) 28 | } 29 | 30 | type DeleteBody = serde::de::IgnoredAny; 31 | 32 | type PostBody = aziot_key_common_http::export_derived_key::Request; 33 | async fn post(self, body: Option) -> http_common::server::RouteResponse { 34 | let body = body.ok_or_else(|| http_common::server::Error { 35 | status_code: http::StatusCode::BAD_REQUEST, 36 | message: "missing request body".into(), 37 | })?; 38 | 39 | let mut api = self.api.lock().await; 40 | let api = &mut *api; 41 | 42 | let derived_key = match api.export_derived_key(&body.handle) { 43 | Ok(derived_key) => derived_key, 44 | Err(err) => return Err(super::to_http_error(&err)), 45 | }; 46 | 47 | let res = aziot_key_common_http::export_derived_key::Response { 48 | key: http_common::ByteString(derived_key), 49 | }; 50 | let res = http_common::server::response::json(hyper::StatusCode::OK, &res); 51 | Ok(res) 52 | } 53 | 54 | type PutBody = serde::de::IgnoredAny; 55 | } 56 | -------------------------------------------------------------------------------- /key/aziot-keys-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-keys-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | serde = { version = "1", optional = true } 10 | url = "2" 11 | 12 | pkcs11 = { path = "../../pkcs11/pkcs11" } 13 | -------------------------------------------------------------------------------- /key/aziot-keys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-keys" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | homepage = "https://azure.github.io/iot-identity-service/" 7 | description = "aziot-keys is the default implementation of cryptographic operations used by the Keys Service." 8 | license = "MIT" 9 | 10 | [lib] 11 | crate-type = ["cdylib"] 12 | 13 | 14 | [dependencies] 15 | foreign-types-shared = "0.1" 16 | hex = "0.4" 17 | hmac = "0.12" 18 | lazy_static = "1" 19 | log = "0.4" 20 | openssl = "0.10" 21 | openssl-sys = "0.9" 22 | sha2 = "0.10" 23 | url = "2" 24 | 25 | aziot-keys-common = { path = "../aziot-keys-common" } 26 | logger = { path = "../../logger" } 27 | openssl2 = { path = "../../openssl2" } 28 | openssl-sys2 = { path = "../../openssl-sys2" } 29 | pkcs11 = { path = "../../pkcs11/pkcs11" } 30 | pkcs11-sys = { path = "../../pkcs11/pkcs11-sys" } 31 | 32 | [features] 33 | # Unused at the moment, but need this so we can present a unified list of features to all packages 34 | snapctl = [] 35 | -------------------------------------------------------------------------------- /key/aziot-keys/cbindgen.prelude.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Microsoft. All rights reserved. 3 | * 4 | * This header specifies the API used for libaziot-keys. This library is used to create and load keys by the Azure IoT Keys Service. 5 | * 6 | * 7 | * # API conventions 8 | * 9 | * All functions return an `unsigned int` to indicate success or failure. See the [`AZIOT_KEYS_RC`] type's docs for details about these constants. 10 | * 11 | * The only function exported by this library is [`aziot_keys_get_function_list`]. Call this function to get the version of the API 12 | * that this library exports, as well as the function pointers to the key operations. See its docs for more details. 13 | * 14 | * All calls to [`aziot_keys_get_function_list`] or any function in [`AZIOT_KEYS_FUNCTION_LIST`] are serialized, ie a function will not be called 15 | * while another function is running. However, it is not guaranteed that all function calls will be made from the same operating system thread. 16 | * Thus, implementations do not need to worry about locking to prevent concurrent access, but should also not store data in thread-local storage. 17 | */ 18 | 19 | -------------------------------------------------------------------------------- /key/aziot-keys/cbindgen.toml: -------------------------------------------------------------------------------- 1 | language = "C" 2 | 3 | no_includes = true 4 | 5 | sys_includes = [ 6 | "stdint.h", # for uintptr_t 7 | ] 8 | 9 | tab_width = 4 10 | 11 | 12 | [fn] 13 | sort_by = "None" 14 | -------------------------------------------------------------------------------- /key/aziot-keys/src/function_list/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | //! Function list types. 4 | 5 | pub mod v2_0_0_0; 6 | 7 | pub mod v2_1_0_0; 8 | 9 | /// The base struct of all of function lists. 10 | #[derive(Debug)] 11 | #[repr(C)] 12 | pub struct AZIOT_KEYS_FUNCTION_LIST { 13 | /// The version of the API represented in this function list. 14 | /// 15 | /// The specific subtype of `AZIOT_KEYS_FUNCTION_LIST` can be determined by inspecting this value. 16 | pub version: crate::AZIOT_KEYS_VERSION, 17 | } 18 | -------------------------------------------------------------------------------- /logger/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "logger" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | env_logger = "0.10" 10 | log = "0.4" 11 | -------------------------------------------------------------------------------- /logger/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(clippy::missing_errors_doc)] 6 | 7 | const LOG_LEVEL_ENV_VAR: &str = "AZIOT_LOG"; 8 | 9 | pub fn try_init() -> Result<(), log::SetLoggerError> { 10 | env_logger::Builder::new() 11 | .format(|fmt, record| { 12 | use std::io::Write; 13 | 14 | let level = match record.level() { 15 | log::Level::Trace => "TRCE", 16 | log::Level::Debug => "DBUG", 17 | log::Level::Info => "INFO", 18 | log::Level::Warn => "WARN", 19 | log::Level::Error => "ERR!", 20 | }; 21 | let timestamp = fmt.timestamp(); 22 | 23 | if record.level() >= log::Level::Debug { 24 | writeln!( 25 | fmt, 26 | "<{}>{} [{}] - [{}] {}", 27 | to_syslog_level(record.level()), 28 | timestamp, 29 | level, 30 | record.target(), 31 | record.args() 32 | ) 33 | } else { 34 | writeln!( 35 | fmt, 36 | "<{}>{} [{}] - {}", 37 | to_syslog_level(record.level()), 38 | timestamp, 39 | level, 40 | record.args() 41 | ) 42 | } 43 | }) 44 | .filter_level(log::LevelFilter::Info) 45 | .parse_env(LOG_LEVEL_ENV_VAR) 46 | .try_init() 47 | } 48 | 49 | fn to_syslog_level(level: log::Level) -> i8 { 50 | match level { 51 | log::Level::Error => 3, 52 | log::Level::Warn => 4, 53 | log::Level::Info => 6, 54 | log::Level::Debug | log::Level::Trace => 7, 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /mini-sntp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mini-sntp" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | publish = false 7 | 8 | [dependencies] 9 | chrono = "0.4" 10 | -------------------------------------------------------------------------------- /openssl-build/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "openssl-build" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | 8 | [dependencies] 9 | cc = "1" 10 | -------------------------------------------------------------------------------- /openssl-build/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(clippy::missing_panics_doc, clippy::must_use_candidate)] 6 | 7 | /// Emits `ossl110` and `ossl330` cfg based on the version of openssl. 8 | pub fn define_version_number_cfg() { 9 | let openssl_version = std::env::var("DEP_OPENSSL_VERSION_NUMBER") 10 | .expect("DEP_OPENSSL_VERSION_NUMBER must have been set by openssl-sys"); 11 | let openssl_version = u64::from_str_radix(&openssl_version, 16) 12 | .expect("DEP_OPENSSL_VERSION_NUMBER must have been set to a valid integer"); 13 | #[allow(clippy::unusual_byte_groupings)] 14 | { 15 | if openssl_version >= 0x03_00_00_00_0 { 16 | println!("cargo:rustc-cfg=ossl300"); 17 | } 18 | 19 | if openssl_version >= 0x01_01_00_00_0 { 20 | println!("cargo:rustc-cfg=ossl110"); 21 | } 22 | } 23 | } 24 | 25 | /// Create an instance of `cc::Build` set up to compile against openssl. 26 | pub fn get_c_compiler() -> cc::Build { 27 | let openssl_include_path = std::env::var_os("DEP_OPENSSL_INCLUDE") 28 | .expect("DEP_OPENSSL_INCLUDE must have been set by openssl-sys"); 29 | 30 | let mut build = cc::Build::new(); 31 | build.include(openssl_include_path); 32 | 33 | build.warnings_into_errors(true); 34 | 35 | build 36 | } 37 | -------------------------------------------------------------------------------- /openssl-sys2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "openssl-sys2" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | build = "build/main.rs" 8 | 9 | [dependencies] 10 | openssl-sys = "0.9" 11 | 12 | [build-dependencies] 13 | openssl-build = { path = "../openssl-build/" } 14 | -------------------------------------------------------------------------------- /openssl-sys2/build/compat.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft. All rights reserved. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 9 | 10 | RSA_METHOD *RSA_meth_dup( 11 | const RSA_METHOD *meth 12 | ) { 13 | // Manually memcpy meth into a new RSA_METHOD. 14 | // The only caveat is meth->name which is a char*, so needs to be strdup'd. 15 | 16 | RSA_METHOD* result = OPENSSL_malloc(sizeof(RSA_METHOD)); 17 | if (result == NULL) { 18 | return NULL; 19 | } 20 | 21 | const char* result_name = OPENSSL_strdup(meth->name); 22 | if (result_name == NULL) { 23 | OPENSSL_free(result); 24 | return NULL; 25 | } 26 | 27 | memcpy(result, meth, sizeof(RSA_METHOD)); 28 | result->name = result_name; 29 | 30 | return result; 31 | } 32 | 33 | int RSA_meth_set_flags(RSA_METHOD *meth, int flags) { 34 | meth->flags = flags; 35 | return 1; 36 | } 37 | 38 | int RSA_meth_set_priv_enc( 39 | RSA_METHOD *rsa, 40 | int (*priv_enc) ( 41 | int flen, 42 | const unsigned char *from, 43 | unsigned char *to, 44 | RSA *rsa, 45 | int padding 46 | ) 47 | ) { 48 | rsa->rsa_priv_enc = priv_enc; 49 | return 1; 50 | } 51 | 52 | int RSA_meth_set_priv_dec( 53 | RSA_METHOD *rsa, 54 | int (*priv_dec) ( 55 | int flen, 56 | const unsigned char *from, 57 | unsigned char *to, 58 | RSA *rsa, 59 | int padding 60 | ) 61 | ) { 62 | rsa->rsa_priv_dec = priv_dec; 63 | return 1; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /openssl-sys2/build/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | openssl_build::define_version_number_cfg(); 8 | 9 | let mut build = openssl_build::get_c_compiler(); 10 | build 11 | .file("build/compat.c") 12 | .compile("openssl_sys2_compat_wrapper"); 13 | } 14 | -------------------------------------------------------------------------------- /openssl-sys2/src/asn1.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | //! `asn1.h` 4 | 5 | extern "C" { 6 | /// Deserializes a DER-encoded octet string. 7 | /// 8 | /// The various subtypes of ASN1_STRING, such as ASN1_OCTET_STRING, are just typedefs to ASN1_STRING. 9 | /// They only exist so that the DER functions, such as d2i_ASN1_OCTET_STRING, are unique for the corresponding DER type. 10 | /// 11 | /// So despite being called d2i_ASN1_OCTET_STRING, this function really does operate on ASN1_STRING instances. 12 | pub fn d2i_ASN1_OCTET_STRING( 13 | a: *mut *mut openssl_sys::ASN1_STRING, 14 | ppin: *mut *const std::os::raw::c_char, 15 | length: std::os::raw::c_long, 16 | ) -> *mut openssl_sys::ASN1_STRING; 17 | } 18 | -------------------------------------------------------------------------------- /openssl-sys2/src/ecdsa.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | //! `ecdsa.h` 4 | 5 | #[cfg(not(ossl110))] 6 | #[repr(C)] 7 | pub struct ECDSA_METHOD([u8; 0]); 8 | 9 | #[cfg(not(ossl110))] 10 | extern "C" { 11 | pub fn ECDSA_size(eckey: *const openssl_sys::EC_KEY) -> std::os::raw::c_int; 12 | 13 | pub fn ECDSA_get_ex_data( 14 | d: *const openssl_sys::EC_KEY, 15 | idx: std::os::raw::c_int, 16 | ) -> *mut std::ffi::c_void; 17 | pub fn ECDSA_set_ex_data( 18 | d: *mut openssl_sys::EC_KEY, 19 | idx: std::os::raw::c_int, 20 | arg: *mut std::ffi::c_void, 21 | ) -> std::os::raw::c_int; 22 | 23 | pub fn ECDSA_set_method( 24 | key: *mut openssl_sys::EC_KEY, 25 | meth: *const ECDSA_METHOD, 26 | ) -> std::os::raw::c_int; 27 | 28 | pub fn ECDSA_OpenSSL() -> *const ECDSA_METHOD; 29 | 30 | pub fn ECDSA_METHOD_new(ecdsa_method: *const ECDSA_METHOD) -> *mut ECDSA_METHOD; 31 | 32 | pub fn ECDSA_METHOD_set_sign( 33 | ecdsa_method: *mut ECDSA_METHOD, 34 | ecdsa_do_sign: Option< 35 | unsafe extern "C" fn( 36 | dgst: *const std::os::raw::c_uchar, 37 | dgst_len: std::os::raw::c_int, 38 | inv: *const openssl_sys::BIGNUM, 39 | rp: *const openssl_sys::BIGNUM, 40 | eckey: *mut openssl_sys::EC_KEY, 41 | ) -> *mut openssl_sys::ECDSA_SIG, 42 | >, 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /openssl-sys2/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(non_camel_case_types, clippy::upper_case_acronyms)] 6 | 7 | mod asn1; 8 | pub use asn1::*; 9 | 10 | mod ec; 11 | pub use ec::*; 12 | 13 | mod ecdsa; 14 | pub use ecdsa::*; 15 | 16 | mod engine; 17 | pub use engine::*; 18 | 19 | mod evp; 20 | pub use evp::*; 21 | 22 | mod rsa; 23 | pub use rsa::*; 24 | 25 | mod x509; 26 | pub use x509::*; 27 | -------------------------------------------------------------------------------- /openssl-sys2/src/rsa.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | //! `rsa.h` 4 | 5 | extern "C" { 6 | pub fn RSA_get_ex_data( 7 | r: *const openssl_sys::RSA, 8 | idx: std::os::raw::c_int, 9 | ) -> *mut std::ffi::c_void; 10 | pub fn RSA_set_ex_data( 11 | r: *mut openssl_sys::RSA, 12 | idx: std::os::raw::c_int, 13 | arg: *mut std::ffi::c_void, 14 | ) -> std::os::raw::c_int; 15 | 16 | pub fn RSA_get_method(rsa: *const openssl_sys::RSA) -> *const openssl_sys::RSA_METHOD; 17 | pub fn RSA_set_method( 18 | rsa: *mut openssl_sys::RSA, 19 | meth: *const openssl_sys::RSA_METHOD, 20 | ) -> std::os::raw::c_int; 21 | 22 | pub fn RSA_get_default_method() -> *const openssl_sys::RSA_METHOD; 23 | } 24 | 25 | extern "C" { 26 | pub fn RSA_meth_dup(meth: *const openssl_sys::RSA_METHOD) -> *mut openssl_sys::RSA_METHOD; 27 | pub fn RSA_meth_set_flags( 28 | meth: *mut openssl_sys::RSA_METHOD, 29 | flags: std::os::raw::c_int, 30 | ) -> std::os::raw::c_int; 31 | pub fn RSA_meth_set_priv_enc( 32 | rsa: *mut openssl_sys::RSA_METHOD, 33 | priv_enc: unsafe extern "C" fn( 34 | flen: std::os::raw::c_int, 35 | from: *const std::os::raw::c_uchar, 36 | to: *mut std::os::raw::c_uchar, 37 | rsa: *mut openssl_sys::RSA, 38 | padding: std::os::raw::c_int, 39 | ) -> std::os::raw::c_int, 40 | ) -> std::os::raw::c_int; 41 | pub fn RSA_meth_set_priv_dec( 42 | rsa: *mut openssl_sys::RSA_METHOD, 43 | priv_dec: unsafe extern "C" fn( 44 | flen: std::os::raw::c_int, 45 | from: *const std::os::raw::c_uchar, 46 | to: *mut std::os::raw::c_uchar, 47 | rsa: *mut openssl_sys::RSA, 48 | padding: std::os::raw::c_int, 49 | ) -> std::os::raw::c_int, 50 | ) -> std::os::raw::c_int; 51 | } 52 | -------------------------------------------------------------------------------- /openssl-sys2/src/x509.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | //! `x509.h` 4 | 5 | extern "C" { 6 | pub fn X509_check_private_key( 7 | x509: *const openssl_sys::X509, 8 | pkey: *const openssl_sys::EVP_PKEY, 9 | ) -> std::os::raw::c_int; 10 | 11 | pub fn X509_EXTENSION_get_data( 12 | ext: *mut openssl_sys::X509_EXTENSION, 13 | ) -> *mut openssl_sys::ASN1_BIT_STRING; 14 | 15 | pub fn X509_EXTENSION_get_object( 16 | ext: *mut openssl_sys::X509_EXTENSION, 17 | ) -> *mut openssl_sys::ASN1_OBJECT; 18 | } 19 | -------------------------------------------------------------------------------- /openssl2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "openssl2" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | build = "build/main.rs" 8 | 9 | 10 | [dependencies] 11 | foreign-types = "0.3" 12 | foreign-types-shared = "0.1" 13 | openssl = "0.10" 14 | openssl-sys = "0.9" 15 | 16 | openssl-sys2 = { path = "../openssl-sys2/" } 17 | 18 | 19 | [build-dependencies] 20 | openssl-build = { path = "../openssl-build/" } 21 | -------------------------------------------------------------------------------- /openssl2/build/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | openssl_build::define_version_number_cfg(); 8 | } 9 | -------------------------------------------------------------------------------- /openssl2/src/extension.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | pub fn parse( 4 | ext: &openssl::x509::X509ExtensionRef, 5 | ) -> (openssl::nid::Nid, &openssl::asn1::Asn1BitStringRef) { 6 | let (obj, data): (&openssl::asn1::Asn1ObjectRef, _) = unsafe { 7 | let ptr = foreign_types_shared::ForeignTypeRef::as_ptr(ext); 8 | 9 | let obj = openssl_sys2::X509_EXTENSION_get_object(ptr); 10 | let data = openssl_sys2::X509_EXTENSION_get_data(ptr); 11 | 12 | ( 13 | foreign_types_shared::ForeignTypeRef::from_ptr(obj), 14 | foreign_types_shared::ForeignTypeRef::from_ptr(data), 15 | ) 16 | }; 17 | 18 | (obj.nid(), data) 19 | } 20 | -------------------------------------------------------------------------------- /pkcs11/pkcs11-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pkcs11-sys" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /pkcs11/pkcs11/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pkcs11" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | 8 | 9 | [dependencies] 10 | foreign-types-shared = "0.1" 11 | lazy_static = "1" 12 | libc = "0.2" 13 | openssl = "0.10" 14 | openssl-sys = "0.9" 15 | percent-encoding = "2" 16 | serde = { version = "1", optional = true } 17 | 18 | openssl2 = { path = "../../openssl2/" } 19 | openssl-sys2 = { path = "../../openssl-sys2/" } 20 | pkcs11-sys = { path = "../pkcs11-sys/" } 21 | 22 | 23 | [build-dependencies] 24 | openssl-build = { path = "../../openssl-build/" } 25 | 26 | 27 | [dev-dependencies] 28 | itertools = "0.10" 29 | -------------------------------------------------------------------------------- /pkcs11/pkcs11/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | openssl_build::define_version_number_cfg(); 8 | } 9 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.73" 3 | components = ["clippy", "rustfmt"] 4 | -------------------------------------------------------------------------------- /snap/hooks/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | toml_kvp() { 4 | printf "%s = \"%s\"\n" "$1" "$2" 5 | } 6 | 7 | toml_new_section() { 8 | printf "\n\n" 9 | printf "[%s]\n" "$1" 10 | } 11 | 12 | snapctl get raw-config > /etc/aziot/config.toml 13 | 14 | $SNAP/bin/aziotctl config apply 15 | -------------------------------------------------------------------------------- /snap/hooks/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 1> >(logger -s -t $(basename $0)) 2>&1 4 | 5 | mkdir -p $SNAP_DATA/shared/{secrets,sockets}/aziot 6 | mkdir -p $SNAP_DATA/shared/config/aziot/{keyd,certd,identityd,tpmd}/config.d 7 | mkdir -p $SNAP_DATA/var/lib/{aziot/{keyd,certd,identityd,tpmd},tpm} 8 | mkdir -p $SNAP_COMMON/libaziot_keys_homedir 9 | -------------------------------------------------------------------------------- /test-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-common" 3 | version = "0.1.0" 4 | license = "MIT" 5 | authors = ["Azure IoT Edge Devs"] 6 | edition = "2021" 7 | 8 | [dependencies] 9 | futures-core = "0.3" 10 | futures-util = "0.3" 11 | hyper = { version = "0.14", features = ["server"] } 12 | openssl = "0.10" 13 | serde_json = "1" 14 | tokio = { version = "1", features = ["net", "parking_lot"] } 15 | tokio-openssl = "0.6" 16 | 17 | aziot-key-client = { path = "../key/aziot-key-client" } 18 | aziot-key-common = { path = "../key/aziot-key-common" } 19 | aziot-identity-common = { path = "../identity/aziot-identity-common" } 20 | aziot-identity-common-http = { path = "../identity/aziot-identity-common-http" } 21 | http-common = { path = "../http-common" } 22 | -------------------------------------------------------------------------------- /test-common/src/client/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | mod cert; 4 | mod identity; 5 | mod key; 6 | 7 | pub use cert::CertClient; 8 | pub use identity::IdentityClient; 9 | pub use key::KeyClient; 10 | pub use key::KeyEngine; 11 | 12 | /// Generic client error. Current tests don't act on the error other 13 | /// than passing it up the call stack, so it's fine to return any error. 14 | fn client_error() -> std::io::Error { 15 | std::io::Error::new(std::io::ErrorKind::Other, "test error") 16 | } 17 | -------------------------------------------------------------------------------- /test-common/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow( 6 | clippy::default_trait_access, 7 | clippy::let_unit_value, 8 | clippy::missing_errors_doc, 9 | clippy::missing_panics_doc, 10 | clippy::module_name_repetitions, 11 | clippy::must_use_candidate 12 | )] 13 | 14 | pub mod client; 15 | pub mod credential; 16 | pub mod tokio_openssl2; 17 | -------------------------------------------------------------------------------- /third-party/cgmanifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "registrations": [ 3 | { 4 | "component": { 5 | "type": "git", 6 | "git": { 7 | "repositoryUrl": "https://github.com/stefanberger/libtpms.git", 8 | "commitHash": "df1c3e98d697f3c1f09262d2ba161a7db784d6cc" 9 | } 10 | } 11 | }, 12 | { 13 | "component": { 14 | "type": "git", 15 | "git": { 16 | "repositoryUrl": "https://github.com/stefanberger/swtpm.git", 17 | "commitHash": "f2268eebb0d1adf89bad83fa4cf91e37b4e3fa53" 18 | } 19 | } 20 | }, 21 | { 22 | "component": { 23 | "type": "git", 24 | "git": { 25 | "repositoryUrl": "https://github.com/tpm2-software/tpm2-tss.git", 26 | "commitHash": "c5f3aed26a0e00215a246910d8521b1c8da34783" 27 | } 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /third-party/generate_cgmanifest.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -eux 2 | 3 | if [ "${1:-}" = "component" ] 4 | then 5 | # CentOS "git submodule foreach" still uses "eval" to pass variables 6 | # to the command string. Variables only began being passed through 7 | # the environment starting in 1.9.0. 8 | SHA=$(git rev-parse HEAD) 9 | URL=$(git ls-remote --get-url) 10 | # $-variables in single-quote string are for jq variable expansion. 11 | # shellcheck disable=SC2016 12 | exec jq -n --arg repositoryUrl "${URL}" --arg commitHash "${SHA}" \ 13 | '{ component: { type: "git", git: { $repositoryUrl, $commitHash } } }' 14 | fi 15 | 16 | SELF=$(readlink -f "${0}") 17 | git submodule foreach --quiet "${SELF} component" \ 18 | | jq -s '{ registrations: . }' 19 | -------------------------------------------------------------------------------- /tpm/aziot-tpm-client-async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-tpm-client-async" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | http = "0.2" 9 | hyper = "0.14" 10 | 11 | aziot-tpm-common = { path = "../aziot-tpm-common" } 12 | aziot-tpm-common-http = { path = "../aziot-tpm-common-http" } 13 | http-common = { path = "../../http-common" } 14 | -------------------------------------------------------------------------------- /tpm/aziot-tpm-common-http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-tpm-common-http" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | serde = { version = "1", features = ["derive"] } 9 | 10 | http-common = { path = "../../http-common" } 11 | -------------------------------------------------------------------------------- /tpm/aziot-tpm-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-tpm-common" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /tpm/aziot-tpm-common/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | pub struct TpmKeys { 7 | pub endorsement_key: Vec, 8 | pub storage_root_key: Vec, 9 | } 10 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-tpmd-config" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | serde = { version = "1", features = ["derive"] } 10 | 11 | http-common = { path = "../../http-common" } 12 | 13 | 14 | [dev-dependencies] 15 | toml = "0.7" 16 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aziot-tpmd" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | async-trait = "0.1" 9 | futures-util = "0.3" 10 | http = "0.2" 11 | hyper = "0.14" 12 | log = "0.4" 13 | serde = "1" 14 | serde_json = "1" 15 | tokio = { version = "1", features = ["parking_lot", "time"] } 16 | url = "2" 17 | 18 | aziot-tpm-common-http = { path = "../aziot-tpm-common-http" } 19 | aziot-tpmd-config = { path = "../aziot-tpmd-config" } 20 | tss-minimal = { path = "../tss-minimal" } 21 | http-common = { path = "../../http-common" } 22 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/aziot-tpmd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT TPM Service 3 | Requires=aziot-tpmd.socket 4 | After=aziot-tpmd.socket 5 | 6 | [Service] 7 | Environment="LD_LIBRARY_PATH=@private-libs@" 8 | ExecStart=@libexecdir@/aziot-identity-service/aziot-tpmd 9 | KillMode=process 10 | Restart=on-failure 11 | RestartSec=5s 12 | User=@user_aziottpm@ 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/aziot-tpmd.socket.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Azure IoT TPM Service API socket 3 | PartOf=aziot-tpmd.service 4 | 5 | [Socket] 6 | ListenStream=@socket_dir@/tpmd.sock 7 | SocketMode=0660 8 | DirectoryMode=0755 9 | SocketUser=@user_aziottpm@ 10 | SocketGroup=@user_aziottpm@ 11 | 12 | [Install] 13 | WantedBy=sockets.target 14 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/config/unix/default.toml: -------------------------------------------------------------------------------- 1 | # This file intentionally left empty because aziot-tpmd has no configurable settings. 2 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/src/http/get_tpm_keys.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use http_common::server::RouteResponse; 4 | 5 | use crate::error::{Error, InternalError}; 6 | 7 | pub(super) struct Route { 8 | api: std::sync::Arc>, 9 | } 10 | 11 | #[async_trait::async_trait] 12 | impl http_common::server::Route for Route { 13 | type ApiVersion = aziot_tpm_common_http::ApiVersion; 14 | fn api_version() -> &'static dyn http_common::DynRangeBounds { 15 | &((aziot_tpm_common_http::ApiVersion::V2020_09_01)..) 16 | } 17 | 18 | type Service = super::Service; 19 | fn from_uri( 20 | server: &Self::Service, 21 | path: &str, 22 | _query: &[(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)], 23 | _extensions: &http::Extensions, 24 | ) -> Option { 25 | if path != "/get_tpm_keys" { 26 | return None; 27 | } 28 | 29 | Some(Route { 30 | api: server.api.clone(), 31 | }) 32 | } 33 | 34 | type DeleteBody = serde::de::IgnoredAny; 35 | 36 | async fn get(self) -> RouteResponse { 37 | let mut api = self.api.lock().await; 38 | let api = &mut *api; 39 | 40 | let (endorsement_key, storage_root_key) = api 41 | .get_tpm_keys() 42 | .map_err(|e| super::to_http_error(&Error::Internal(InternalError::GetTpmKeys(e))))?; 43 | 44 | let res = aziot_tpm_common_http::get_tpm_keys::Response { 45 | /// The TPM's Endorsement Key 46 | endorsement_key: http_common::ByteString(endorsement_key), 47 | /// The TPM's Storage Root Key 48 | storage_root_key: http_common::ByteString(storage_root_key), 49 | }; 50 | 51 | let res = http_common::server::response::json(hyper::StatusCode::OK, &res); 52 | Ok(res) 53 | } 54 | 55 | type PostBody = serde::de::IgnoredAny; 56 | 57 | type PutBody = serde::de::IgnoredAny; 58 | } 59 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/src/http/import_auth_key.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use http_common::server::RouteResponse; 4 | 5 | use crate::error::{Error, InternalError}; 6 | 7 | pub(super) struct Route { 8 | api: std::sync::Arc>, 9 | } 10 | 11 | #[async_trait::async_trait] 12 | impl http_common::server::Route for Route { 13 | type ApiVersion = aziot_tpm_common_http::ApiVersion; 14 | fn api_version() -> &'static dyn http_common::DynRangeBounds { 15 | &((aziot_tpm_common_http::ApiVersion::V2020_09_01)..) 16 | } 17 | 18 | type Service = super::Service; 19 | fn from_uri( 20 | server: &Self::Service, 21 | path: &str, 22 | _query: &[(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)], 23 | _extensions: &http::Extensions, 24 | ) -> Option { 25 | if path != "/import_auth_key" { 26 | return None; 27 | } 28 | 29 | Some(Route { 30 | api: server.api.clone(), 31 | }) 32 | } 33 | 34 | type DeleteBody = serde::de::IgnoredAny; 35 | 36 | type PostBody = aziot_tpm_common_http::import_auth_key::Request; 37 | async fn post(self, body: Option) -> RouteResponse { 38 | let body = body.ok_or_else(|| http_common::server::Error { 39 | status_code: http::StatusCode::BAD_REQUEST, 40 | message: "missing request body".into(), 41 | })?; 42 | 43 | let mut api = self.api.lock().await; 44 | let api = &mut *api; 45 | 46 | api.import_auth_key(&body.key.0) 47 | .map_err(|e| super::to_http_error(&Error::Internal(InternalError::ImportAuthKey(e))))?; 48 | 49 | let res = aziot_tpm_common_http::import_auth_key::Response {}; 50 | let res = http_common::server::response::json(hyper::StatusCode::OK, &res); 51 | Ok(res) 52 | } 53 | 54 | type PutBody = serde::de::IgnoredAny; 55 | } 56 | -------------------------------------------------------------------------------- /tpm/aziot-tpmd/src/http/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | mod get_tpm_keys; 4 | mod import_auth_key; 5 | mod sign_with_auth_key; 6 | 7 | #[derive(Clone)] 8 | pub struct Service { 9 | pub(crate) api: std::sync::Arc>, 10 | } 11 | 12 | http_common::make_service! { 13 | service: Service, 14 | api_version: aziot_tpm_common_http::ApiVersion, 15 | routes: [ 16 | get_tpm_keys::Route, 17 | import_auth_key::Route, 18 | sign_with_auth_key::Route, 19 | ], 20 | } 21 | 22 | fn to_http_error(err: &crate::Error) -> http_common::server::Error { 23 | let error_message = http_common::server::error_to_message(err); 24 | 25 | // TODO: When we get distributed tracing, associate these logs with the tracing ID. 26 | for line in error_message.lines() { 27 | log::log!( 28 | match err { 29 | crate::Error::Internal(_) => log::Level::Error, 30 | }, 31 | "!!! {}", 32 | line, 33 | ); 34 | } 35 | 36 | match err { 37 | // Do not use error_message because we don't want to leak internal errors to the client. 38 | // Just return the top-level error, ie "internal error" 39 | crate::Error::Internal(_) => http_common::server::Error { 40 | status_code: hyper::StatusCode::INTERNAL_SERVER_ERROR, 41 | message: err.to_string().into(), 42 | }, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tpm/tss-minimal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tss-minimal" 3 | version = "0.1.0" 4 | authors = ["Azure IoT Edge Devs"] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | log = "0.4" 11 | paste = "1" 12 | 13 | esys-sys = { path = "./esys-sys" } 14 | mu-sys = { path = "./mu-sys" } 15 | rc-sys = { path = "./rc-sys" } 16 | tcti-sys = { path = "./tcti-sys" } 17 | types-sys = { path = "./types-sys" } 18 | 19 | [dev-dependencies] 20 | env_logger = "0.10" 21 | -------------------------------------------------------------------------------- /tpm/tss-minimal/esys-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esys-sys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | links = "tss2-esys" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | tcti-sys = { path = "../tcti-sys" } 11 | types-sys = { path = "../types-sys" } 12 | 13 | [build-dependencies] 14 | bindgen = { version = "0.69", features = ["runtime"], default-features = false } 15 | # NOTE: Version >= 0.3.20 necessary for cross-builds. 16 | # Ref: https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md#0320---2021-09-25 17 | pkg-config = "0.3.20" 18 | -------------------------------------------------------------------------------- /tpm/tss-minimal/esys-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(non_camel_case_types, non_snake_case, clippy::borrow_as_ptr)] 6 | // https://github.com/rust-lang/rust-bindgen/pull/2230 7 | #![cfg_attr(test, allow(clippy::items_after_statements))] 8 | 9 | use tcti_sys::TSS2_TCTI_CONTEXT; 10 | // TPMI_RH_HIERARCHY is required on 2.3.2 (non-exhaustive) 11 | #[allow(unused_imports)] 12 | use types_sys::TPMI_RH_HIERARCHY; 13 | use types_sys::{ 14 | TPM2B_AUTH, TPM2B_CREATION_DATA, TPM2B_DATA, TPM2B_DIGEST, TPM2B_ENCRYPTED_SECRET, 15 | TPM2B_ID_OBJECT, TPM2B_MAX_BUFFER, TPM2B_NAME, TPM2B_NONCE, TPM2B_PRIVATE, TPM2B_PUBLIC, 16 | TPM2B_SENSITIVE_CREATE, TPM2B_TIMEOUT, TPM2_HANDLE, TPM2_SE, TPMI_ALG_HASH, TPMI_DH_PERSISTENT, 17 | TPML_PCR_SELECTION, TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT, TPMT_TK_AUTH, TPMT_TK_CREATION, 18 | TPMT_TK_HASHCHECK, 19 | }; 20 | 21 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | // Check for presence 26 | #[allow(unused_imports)] 27 | use super::{ 28 | ESYS_TR_NONE, ESYS_TR_PASSWORD, ESYS_TR_RH_ENDORSEMENT, ESYS_TR_RH_NULL, ESYS_TR_RH_OWNER, 29 | ESYS_TR_RH_PLATFORM, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /tpm/tss-minimal/esys-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /tpm/tss-minimal/mu-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mu-sys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | links = "tss2-mu" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | types-sys = { path = "../types-sys" } 11 | 12 | [build-dependencies] 13 | bindgen = { version = "0.69", features = ["runtime"], default-features = false } 14 | # NOTE: Version >= 0.3.20 necessary for cross-builds. 15 | # Ref: https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md#0320---2021-09-25 16 | pkg-config = "0.3.20" 17 | -------------------------------------------------------------------------------- /tpm/tss-minimal/mu-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] 6 | // https://github.com/rust-lang/rust-bindgen/pull/2230 7 | #![cfg_attr(test, allow(clippy::items_after_statements))] 8 | 9 | use types_sys::{TPM2B_ENCRYPTED_SECRET, TPM2B_ID_OBJECT, TPM2B_PRIVATE, TPM2B_PUBLIC}; 10 | 11 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 12 | -------------------------------------------------------------------------------- /tpm/tss-minimal/mu-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /tpm/tss-minimal/rc-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rc-sys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | links = "tss2-rc" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [build-dependencies] 10 | bindgen = { version = "0.69", features = ["runtime"], default-features = false } 11 | # NOTE: Version >= 0.3.20 necessary for cross-builds. 12 | # Ref: https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md#0320---2021-09-25 13 | pkg-config = "0.3.20" 14 | -------------------------------------------------------------------------------- /tpm/tss-minimal/rc-sys/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | println!("cargo:rerun-if-changed=wrapper.h"); 8 | println!("cargo:rerun-if-env-changed=VENDOR_PREFIX"); 9 | println!("cargo:rerun-if-env-changed=VENDOR_PKGCONFIG"); 10 | 11 | if let Some((fakeroot, pkgconfig)) = 12 | std::env::var_os("VENDOR_PREFIX").zip(std::env::var_os("VENDOR_PKGCONFIG")) 13 | { 14 | if std::path::Path::new(&fakeroot).exists() { 15 | std::env::set_var("PKG_CONFIG_SYSROOT_DIR", fakeroot); 16 | std::env::set_var("PKG_CONFIG_PATH", pkgconfig); 17 | } 18 | } 19 | 20 | let lib_cfg = pkg_config::Config::new() 21 | .atleast_version("2.3.0") // tss2-rc introduction 22 | .probe("tss2-rc") 23 | .unwrap(); 24 | 25 | for lib in lib_cfg.libs { 26 | println!("cargo:rustc-link-lib={lib}"); 27 | } 28 | 29 | for path in lib_cfg.link_paths { 30 | println!("cargo:rustc-link-search={}", path.to_str().unwrap()); 31 | } 32 | 33 | let bindings = bindgen::Builder::default() 34 | .header("wrapper.h") 35 | .allowlist_function("Tss2_RC_Decode") 36 | .clang_args( 37 | lib_cfg 38 | .include_paths 39 | .into_iter() 40 | .map(|path| format!("-I{}", path.to_str().unwrap())), 41 | ) 42 | .generate() 43 | .unwrap(); 44 | 45 | let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()); 46 | bindings 47 | .write_to_file(out_path.join("bindings.rs")) 48 | .unwrap(); 49 | } 50 | -------------------------------------------------------------------------------- /tpm/tss-minimal/rc-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] 6 | // https://github.com/rust-lang/rust-bindgen/pull/2230 7 | #![cfg_attr(test, allow(clippy::items_after_statements))] 8 | 9 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 10 | -------------------------------------------------------------------------------- /tpm/tss-minimal/rc-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /tpm/tss-minimal/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | use std::ffi::CStr; 4 | use std::fmt; 5 | 6 | macro_rules! wrap_rc { 7 | ($e:expr) => {{ 8 | let rc = unsafe { $e }; 9 | if rc > 0 { 10 | Err($crate::Error(rc)) 11 | } else { 12 | Ok(()) 13 | } 14 | }}; 15 | } 16 | 17 | pub(crate) use wrap_rc; 18 | 19 | pub fn try_decode_rc(rc: u32) -> Option { 20 | let msg = unsafe { rc_sys::Tss2_RC_Decode(rc) }; 21 | 22 | if msg.is_null() { 23 | return None; 24 | } 25 | 26 | let cstr = unsafe { CStr::from_ptr(msg) }; 27 | cstr.to_str().ok().map(ToOwned::to_owned) 28 | } 29 | 30 | pub type Result = std::result::Result; 31 | 32 | #[derive(Debug)] 33 | pub struct Error(pub(crate) u32); 34 | 35 | impl fmt::Display for Error { 36 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 37 | write!( 38 | f, 39 | "{}", 40 | try_decode_rc(self.0).as_deref().unwrap_or("unknown") 41 | ) 42 | } 43 | } 44 | 45 | impl std::error::Error for Error {} 46 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tcti-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tcti-sys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | links = "tss2-tctildr" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [build-dependencies] 10 | bindgen = { version = "0.69", features = ["runtime"], default-features = false } 11 | # NOTE: Version >= 0.3.20 necessary for cross-builds. 12 | # Ref: https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md#0320---2021-09-25 13 | pkg-config = "0.3.20" 14 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tcti-sys/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | fn main() { 7 | println!("cargo:rerun-if-changed=wrapper.h"); 8 | println!("cargo:rerun-if-env-changed=VENDOR_PREFIX"); 9 | println!("cargo:rerun-if-env-changed=VENDOR_PKGCONFIG"); 10 | 11 | if let Some((fakeroot, pkgconfig)) = 12 | std::env::var_os("VENDOR_PREFIX").zip(std::env::var_os("VENDOR_PKGCONFIG")) 13 | { 14 | if std::path::Path::new(&fakeroot).exists() { 15 | std::env::set_var("PKG_CONFIG_SYSROOT_DIR", fakeroot); 16 | std::env::set_var("PKG_CONFIG_PATH", pkgconfig); 17 | } 18 | } 19 | 20 | let lib_cfg = pkg_config::Config::new() 21 | .atleast_version("2.3.0") // tss2-tctildr introduction 22 | .probe("tss2-tctildr") 23 | .unwrap(); 24 | 25 | for lib in lib_cfg.libs { 26 | println!("cargo:rustc-link-lib={lib}"); 27 | } 28 | 29 | for path in lib_cfg.link_paths { 30 | println!("cargo:rustc-link-search={}", path.to_str().unwrap()); 31 | } 32 | 33 | let bindings = bindgen::Builder::default() 34 | .header("wrapper.h") 35 | .allowlist_function("Tss2_TctiLdr_Finalize") 36 | .allowlist_function("Tss2_TctiLdr_Initialize") 37 | .clang_args( 38 | lib_cfg 39 | .include_paths 40 | .into_iter() 41 | .map(|path| format!("-I{}", path.to_str().unwrap())), 42 | ) 43 | .generate() 44 | .unwrap(); 45 | 46 | let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()); 47 | bindings 48 | .write_to_file(out_path.join("bindings.rs")) 49 | .unwrap(); 50 | } 51 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tcti-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] 6 | // https://github.com/rust-lang/rust-bindgen/pull/2230 7 | #![cfg_attr(test, allow(clippy::items_after_statements))] 8 | 9 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 10 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tcti-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tests/create_primary.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | #[test] 7 | fn main() -> tss_minimal::Result<()> { 8 | let _ = env_logger::builder().is_test(true).try_init(); 9 | 10 | let ctx = tss_minimal::EsysContext::new(&std::ffi::CString::default())?; 11 | 12 | let _handle = ctx.create_primary( 13 | &tss_minimal::Persistent::PASSWORD_SESSION, 14 | tss_minimal::Persistent::ENDORSEMENT_HIERARCHY, 15 | unsafe { &std::mem::zeroed() }, 16 | &tss_minimal::types::EK_RSA_TEMPLATE, 17 | None, 18 | )?; 19 | 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tests/evict_control.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | #[test] 7 | fn main() -> tss_minimal::Result<()> { 8 | let _ = env_logger::builder().is_test(true).try_init(); 9 | 10 | let ctx = tss_minimal::EsysContext::new(&std::ffi::CString::default())?; 11 | 12 | let handle = ctx.create_primary( 13 | &tss_minimal::Persistent::PASSWORD_SESSION, 14 | tss_minimal::Persistent::ENDORSEMENT_HIERARCHY, 15 | unsafe { &std::mem::zeroed() }, 16 | &tss_minimal::types::EK_RSA_TEMPLATE, 17 | None, 18 | )?; 19 | 20 | let handle = ctx 21 | .evict( 22 | tss_minimal::Persistent::OWNER_HIERARCHY, 23 | &handle, 24 | &tss_minimal::Persistent::PASSWORD_SESSION, 25 | 0x8101_0001, 26 | )? 27 | .unwrap(); 28 | 29 | let handle = ctx.evict( 30 | tss_minimal::Persistent::OWNER_HIERARCHY, 31 | &handle, 32 | &tss_minimal::Persistent::PASSWORD_SESSION, 33 | 0, 34 | )?; 35 | 36 | assert!(handle.is_none()); 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tests/from_tpm_public.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | #[test] 7 | fn main() -> tss_minimal::Result<()> { 8 | let _ = env_logger::builder().is_test(true).try_init(); 9 | 10 | let ctx = tss_minimal::EsysContext::new(&std::ffi::CString::default())?; 11 | 12 | let handle = ctx.create_primary( 13 | &tss_minimal::Persistent::PASSWORD_SESSION, 14 | tss_minimal::Persistent::ENDORSEMENT_HIERARCHY, 15 | unsafe { &std::mem::zeroed() }, 16 | &tss_minimal::types::EK_RSA_TEMPLATE, 17 | None, 18 | )?; 19 | 20 | let _handle_persistent = ctx.evict( 21 | tss_minimal::Persistent::OWNER_HIERARCHY, 22 | &handle, 23 | &tss_minimal::Persistent::PASSWORD_SESSION, 24 | 0x8101_0001, 25 | )?; 26 | 27 | let handle = ctx.from_tpm_public(0x8101_0001, None)?; 28 | 29 | let handle = ctx.evict( 30 | tss_minimal::Persistent::OWNER_HIERARCHY, 31 | &handle, 32 | &tss_minimal::Persistent::PASSWORD_SESSION, 33 | 0, 34 | )?; 35 | 36 | assert!(handle.is_none()); 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /tpm/tss-minimal/tests/policy_secret.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | 6 | #[test] 7 | fn main() -> tss_minimal::Result<()> { 8 | let _ = env_logger::builder().is_test(true).try_init(); 9 | 10 | let ctx = tss_minimal::EsysContext::new(&std::ffi::CString::default())?; 11 | let auth_session = tss_minimal::Persistent::PASSWORD_SESSION; 12 | 13 | let sym = types_sys::TPMT_SYM_DEF { 14 | algorithm: tss_minimal::types::sys::DEF_TPM2_ALG_AES, 15 | keyBits: tss_minimal::types::sys::TPMU_SYM_KEY_BITS { aes: 256 }, 16 | mode: tss_minimal::types::sys::TPMU_SYM_MODE { 17 | aes: tss_minimal::types::sys::DEF_TPM2_ALG_CFB, 18 | }, 19 | }; 20 | 21 | let mut auth = ctx.start_auth_session( 22 | tss_minimal::types::sys::DEF_TPM2_SE_POLICY, 23 | &sym, 24 | tss_minimal::types::sys::DEF_TPM2_ALG_SHA256, 25 | )?; 26 | tss_minimal::Policy::new( 27 | tss_minimal::PolicyKind::Secret { 28 | handle: &tss_minimal::Persistent::ENDORSEMENT_HIERARCHY, 29 | auth: &auth_session, 30 | }, 31 | &ctx, 32 | ) 33 | .apply(&mut auth)?; 34 | 35 | let dgst = ctx.policy_digest(&auth)?; 36 | let expected: [u8; 32] = [ 37 | 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, 0x46, 0xA5, 0xD7, 38 | 0x24, 0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, 39 | 0x69, 0xAA, 40 | ]; 41 | 42 | assert_eq!(expected, dgst.buffer[..dgst.size as _]); 43 | 44 | Ok(()) 45 | } 46 | -------------------------------------------------------------------------------- /tpm/tss-minimal/types-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "types-sys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [build-dependencies] 9 | bindgen = { version = "0.69", features = ["runtime"], default-features = false } 10 | # NOTE: Version >= 0.3.20 necessary for cross-builds. 11 | # Ref: https://github.com/rust-lang/pkg-config-rs/blob/master/CHANGELOG.md#0320---2021-09-25 12 | pkg-config = "0.3.20" 13 | -------------------------------------------------------------------------------- /tpm/tss-minimal/types-sys/const_define.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -eux 2 | 3 | # `bindgen` cannot expand macros of the form "#define CONSTANT ((TYPE) 4 | # VALUE)". This script converts such macros to "const" declarations. 5 | # Ref: https://github.com/rust-lang/rust-bindgen/issues/316 6 | 7 | HEADER=$(find "${1}" -name tss2_tpm2_types.h) 8 | test -n "${HEADER}" 9 | ( 10 | IFS=, 11 | for KEY in ${2} 12 | do 13 | PREFIX=${KEY%:*} 14 | ALIAS=${KEY#*:} 15 | grep "define ${PREFIX}" "${HEADER}" \ 16 | | awk -v ALIAS="${ALIAS}" '{ print ALIAS" const DEF_"$2" = "$2";" }' 17 | done 18 | ) \ 19 | | cat wrapper.h.in - 20 | -------------------------------------------------------------------------------- /tpm/tss-minimal/types-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | 3 | #![deny(rust_2018_idioms)] 4 | #![warn(clippy::all, clippy::pedantic)] 5 | #![allow( 6 | non_camel_case_types, 7 | non_snake_case, 8 | non_upper_case_globals, 9 | clippy::missing_safety_doc, 10 | clippy::unreadable_literal 11 | )] 12 | #![cfg_attr(test, allow(clippy::too_many_lines))] 13 | // https://github.com/rust-lang/rust-bindgen/pull/2230 14 | #![cfg_attr(test, allow(clippy::items_after_statements))] 15 | 16 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | // Check for presence 21 | #[allow(unused_imports)] 22 | use super::{DEF_TPM2_HR_PERSISTENT, DEF_TPM2_SE_HMAC, DEF_TPM2_SE_POLICY, DEF_TPM2_SE_TRIAL}; 23 | } 24 | -------------------------------------------------------------------------------- /tpm/tss-minimal/types-sys/wrapper.h.in: -------------------------------------------------------------------------------- 1 | #include 2 | --------------------------------------------------------------------------------