diff --git a/amber-cli-tdx/README.md b/amber-cli-tdx/README.md index ace0f01..31beb1c 100644 --- a/amber-cli-tdx/README.md +++ b/amber-cli-tdx/README.md @@ -1,74 +1,6 @@ # Intel Project Amber Go TDX CLI This is the beta version of Go TDX CLI for integrating with Intel Project Amber V1 API. -You can view Intel Project Amber API docs here: [https://intel.github.io/amber-docs/rest/overview/](https://intel.github.io/amber-docs/rest/overview/) - -## Prerequisites - -The Amber Client TDX CLI has dependency on Intel SGX DCAP. Install TDX Attestation library devel packages from Intel SGX DCAP. - -### For Ubuntu* OS -Install the Debian package for `libtdx-attest-dev` following these steps: - -1. Add the following repository to your sources: - * For Ubuntu* 18.04: - ```sh - echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu bionic main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list - ``` - * For Ubuntu* 20.04: - ```sh - echo 'deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list - ``` - * For Ubuntu* 22.04: - ```sh - echo 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list - ``` -2. Get the Debian repo public key and add it to the list of trusted keys that are used by apt to authenticate packages: - * For Ubuntu* 18.04 and Ubuntu* 20.04: - ```sh - wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - ``` - * For Ubuntu* 22.04: - ```sh - wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key - cat intel-sgx-deb.key | sudo tee /etc/apt/keyrings/intel-sgx-keyring.asc > /dev/null - ``` -3. Update apt and install the *libtdx-attest-dev* package: - ```sh - sudo apt-get update - sudo apt-get install libtdx-attest-dev - ``` - -### For RHEL* OS -Install the RPM package for `libtdx-attest-devel` following these steps: - -1. Find RPM packages for DCAP libraries and services, which are currently provided in a single TAR archive at - ``` - https://download.01.org/intel-sgx/latest/linux-latest/distro// - ``` -2. Download the file `sgx_rpm_local_repo.tgz` to a selected folder, for example `/opt/intel` - ```sh - cd /opt/intel - sudo wget https://download.01.org/intel-sgx/latest/linux-latest/distro//sgx_rpm_local_repo.tgz - ``` -3. Verify the downloaded repo file with the SHA value in this file: - https://download.01.org/intel-sgx/latest/dcap-latest/linux/SHA256SUM_dcap_.cfg - ```sh - sha256sum sgx_rpm_local_repo.tgz - ``` -4. Expand the archive: - ```sh - sudo tar xvf sgx_rpm_local_repo.tgz - ``` -5. Add the RPM local repository to your local repository list - ```sh - sudo yum-config-manager --add-repo file://PATH_TO_LOCAL_REPO - ``` -6. Install all the latest packages using `sudo dnf --nogpgcheck install ` - ```sh - sudo dnf --nogpgcheck install libtdx-attest-devel - ``` - ## Go Requirement Use go1.17 or newer. @@ -83,13 +15,6 @@ cd amber-cli-tdx/ make cli ``` -### Install prebuilt binary -Install the latest version of the CLI with the following commands: - -```sh -go get github.com/intel/amber/v1/client/tdx-cli -``` - ## Usage Amber Client TDX CLI exposes help option to get a list of all the @@ -106,6 +31,18 @@ export AMBER_URL= export AMBER_API_KEY= amber-cli token --user-data --policy-ids ``` +OR +```sh +amber-cli token --pub-path --policy-ids +``` + +### To verify an Amber signed token + +```sh +export AMBER_URL= +export AMBER_API_KEY= +amber-cli verify --token-path +``` ### To get a TD quote with Nonce and UserData @@ -126,7 +63,7 @@ amber-cli decrypt --key --in ``` ## License diff --git a/amber-cli-tdx/cmd/quote.go b/amber-cli-tdx/cmd/quote.go index aaa83c3..e0c9f5e 100644 --- a/amber-cli-tdx/cmd/quote.go +++ b/amber-cli-tdx/cmd/quote.go @@ -66,8 +66,7 @@ func getQuote(cmd *cobra.Command) error { } } - evLogParser := tdx.NewEventLogParser() - adapter, err := tdx.NewAdapter(userDataBytes, evLogParser) + adapter, err := tdx.NewAzureAdapter(userDataBytes, nil) if err != nil { return errors.Wrap(err, "Error while creating tdx adapter") } @@ -76,6 +75,6 @@ func getQuote(cmd *cobra.Command) error { return errors.Wrap(err, "Failed to collect evidence") } - fmt.Fprintln(os.Stdout, evidence.Evidence) + fmt.Fprintln(os.Stdout, base64.StdEncoding.EncodeToString(evidence.Evidence)) return nil } diff --git a/amber-cli-tdx/cmd/token.go b/amber-cli-tdx/cmd/token.go index 9575906..75a2c06 100644 --- a/amber-cli-tdx/cmd/token.go +++ b/amber-cli-tdx/cmd/token.go @@ -133,8 +133,7 @@ func getToken(cmd *cobra.Command) error { return err } - evLogParser := tdx.NewEventLogParser() - adapter, err := tdx.NewAdapter(userDataBytes, evLogParser) + adapter, err := tdx.NewAzureAdapter(userDataBytes, nil) if err != nil { return errors.Wrap(err, "Error while creating tdx adapter") } diff --git a/amber-cli-tdx/cmd/token_verify.go b/amber-cli-tdx/cmd/token_verify.go new file mode 100644 index 0000000..f4f9553 --- /dev/null +++ b/amber-cli-tdx/cmd/token_verify.go @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 Intel Corporation + * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +package cmd + +import ( + "crypto/tls" + "encoding/base64" + "fmt" + "net/url" + "os" + + "github.com/intel/amber/v1/client" + "github.com/intel/amber/v1/client/tdx-cli/constants" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// verifyCmd represents the token command +var verifyCmd = &cobra.Command{ + Use: constants.VerifyCmd, + Short: "Verify the amber token", + Long: ``, + RunE: func(cmd *cobra.Command, args []string) error { + err := verifyToken(cmd) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + return err + } + + return nil + }, +} + +func init() { + rootCmd.AddCommand(verifyCmd) + verifyCmd.Flags().StringP(constants.VerifyTokenOption, "f", "", "Path to token file") +} + +func verifyToken(cmd *cobra.Command) error { + var err error + + viper.AutomaticEnv() + amberUrl := viper.GetString(constants.AmberUrlEnv) + if amberUrl == "" { + return errors.Errorf("%s is not set in env", constants.AmberUrlEnv) + } else { + _, err = url.ParseRequestURI(amberUrl) + if err != nil { + return errors.Wrap(err, "Invalid Amber URL") + } + } + + amberApikey := viper.GetString(constants.AmberApiKeyEnv) + if amberApikey == "" { + return errors.Errorf("%s is not set in env", constants.AmberApiKeyEnv) + } else { + _, err = base64.URLEncoding.DecodeString(amberApikey) + if err != nil { + return errors.Wrap(err, "Invalid Api key, must be base64 string") + } + } + + tokenPath, err := cmd.Flags().GetString(constants.VerifyTokenOption) + if err != nil { + return err + } + + var token []byte + if tokenPath != "" { + token, err = os.ReadFile(tokenPath) + if err != nil { + return errors.Wrap(err, "Error reading token from file") + } + + } + + tlsConfig := &tls.Config{ + InsecureSkipVerify: false, + MinVersion: tls.VersionTLS12, + } + + cfg := client.Config{ + Url: amberUrl, + TlsCfg: tlsConfig, + ApiKey: amberApikey, + } + + amberClient, err := client.New(&cfg) + if err != nil { + return err + } + + status, err := amberClient.VerifyToken(string(token)) + if err != nil { + return err + } + + fmt.Fprintln(os.Stdout, status) + return nil +} diff --git a/amber-cli-tdx/cmd/token_verify_test.go b/amber-cli-tdx/cmd/token_verify_test.go new file mode 100644 index 0000000..1000d35 --- /dev/null +++ b/amber-cli-tdx/cmd/token_verify_test.go @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022 Intel Corporation + * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ + +package cmd + +import ( + "github.com/intel/amber/v1/client/tdx-cli/constants" + "github.com/intel/amber/v1/client/tdx-cli/test" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +const ( + tokenPath = "token.jwt" + tokenMissingKIDPath = "tokenMissingKID.jwt" + tokenInvalidKIDPath = "tokenInvalidKID.jwt" + tokenMissingJKUPath = "tokenMissingJKU.jwt" + tokenInvalidJKUPath = "tokenInvalidJKU.jwt" + tokenMalformedJKUPath = "tokenMalformedJKU.jwt" +) + +var ( + token = "eyJhbGciOiJQUzM4NCIsImprdSI6Imh0dHBzOi8vd3d3LmludGVsLmNvbS9hbWJlci9jZXJ0cyIsImtpZCI6IjNjMjQxOGI1ZTY5ZTI2NDRiOTE2NzJmZjYwNTY2NjRkOTI0MjM0ZjAiLCJ0eXAiOiJKV1QifQ.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" + tokenMissingKID = "eyJhbGciOiJQUzM4NCIsImprdSI6Imh0dHBzOi8vd3d3LmludGVsLmNvbS9hbWJlci9jZXJ0cyIsInR5cCI6IkpXVCJ9.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" + tokenInvalidKID = "ewogICJhbGciOiAiUFMzODQiLAogICJqa3UiOiAiaHR0cHM6Ly93d3cuaW50ZWwuY29tL2FtYmVyL2NlcnRzIiwKICAia2lkIjogMTIzLAogICJ0eXAiOiAiSldUIgp9.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" + tokenMissingJKU = "ewogICJhbGciOiAiUFMzODQiLAogICJraWQiOiAiM2MyNDE4YjVlNjllMjY0NGI5MTY3MmZmNjA1NjY2NGQ5MjQyMzRmMCIsCiAgInR5cCI6ICJKV1QiCn0.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" + tokenInvalidJKU = "ewogICJhbGciOiAiUFMzODQiLAogICJqa3UiOiAxMjMsCiAgImtpZCI6ICIzYzI0MThiNWU2OWUyNjQ0YjkxNjcyZmY2MDU2NjY0ZDkyNDIzNGYwIiwKICAidHlwIjogIkpXVCIKfQ.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" + tokenMalformedJKU = "ewogICJhbGciOiAiUFMzODQiLAogICJqa3UiOiAiYm9ndXNcbmJhc2VcblVSTCIsCiAgImtpZCI6ICIzYzI0MThiNWU2OWUyNjQ0YjkxNjcyZmY2MDU2NjY0ZDkyNDIzNGYwIiwKICAidHlwIjogIkpXVCIKfQ.eyJhbWJlcl90cnVzdF9zY29yZSI6MTAsImFtYmVyX3JlcG9ydF9kYXRhIjoiZWZmNWEyYTExNDg2N2FhOTQ0NjIwYzQ4Y2Q4NjcwNDZkYmY2ZjdmY2JmODQ5YTliNjZhNzg3MjJmNGRjZDdjOTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJhbWJlcl90ZWVfaGVsZF9kYXRhIjoiQVFBQkFLMkxyUDhSZ1ROMW5naFJZWTBKQnZZQ1M3K2JCcVhoRjIzY2JkVFVRR3F3MEl2Wm9NYkpySUNmQXJ1MjVWWWpKbkZaS0Vvb1hRWmhPZUlBeTZNV0RpWEpmdDc0VnVUR25YZnNLUDk4bWNvZXBiQ2M4U1BJRFBsdkhTQy9QQWtlRzJUdlZ3QkhBbjcvcURVNXJwUENIS05xWDYweUd2SW95QjhrLzBJTzR5M2V0ekdvQjF5YVRPQ3Iyd1NCYmdUUkV1M3ppY3JJODFPL1RsK0FaWitVekFCdUxSUEgxdlBrelBQYVhCT21IN2Q4SnZXZ0RwSjhFenBNRitzakt4dXI1dkEraDNjamxDUG4yZjFjODhqZGIyNDgyUUJ2STZoanB4R2k0dWRUVVdJekdKdElKeElUbnNscThwTFpUekhnR3V2UEdYK2xkYWFKdUVPSGJBeFhDRW4zTnNGNHZvVjFSQ2I1OXBBMEI2NnZBd1RHZmFONE9pR205aGhiTk1NTnZNeGlhZmdGanJWWHpjc1BvUE5vN2hPd0dMcVJFdGUrMWkzZzlGNDBCK2hEZVV6elZhTU8zVkxHTUtEcDlUSDJqMytYSnRnU3p4dThOWlg1WEZVeGpSMlJINzV5d25vbnRNQStnaDZid1d1UUlWWWI2K0k3eHEzdWxOaUZldzZ4eWc9PSIsImFtYmVyX3NneF9tcmVuY2xhdmUiOiI4M2Y0ZTgxOTg2MWFkZWY2ZmZiMmE0ODY1ZWZlYTkzMzdiOTFlZDMwZmEzMzQ5MWIxN2YwZDVkOWU4MjA0NDEwIiwiYW1iZXJfc2d4X2lzX2RlYnVnZ2FibGUiOmZhbHNlLCJhbWJlcl9zZ3hfbXJzaWduZXIiOiI4M2Q3MTllNzdkZWFjYTE0NzBmNmJhZjYyYTRkNzc0MzAzYzg5OWRiNjkwMjBmOWM3MGVlMWRmYzA4YzdjZTllIiwiYW1iZXJfc2d4X2lzdnByb2RpZCI6MCwiYW1iZXJfc2d4X2lzdnN2biI6MCwiYW1iZXJfbWF0Y2hlZF9wb2xpY3lfaWRzIjpbImY0MzZjMzBhLTY0NGUtNGJiMi1iMzJjLTFmNWJmZjc3NTJmMiJdLCJhbWJlci1mYWl0aGZ1bC1zZXJ2aWNlLWlkcyI6WyI2YmFhNjMwMS0zMWVlLTQ1NmMtOWEzOC1lMjc5YWM3ZjZkNmEiLCJkZTU3NDU5ZC1mYjU2LTRhODgtYmU1ZC02ZjJhMzcwMzkzOWMiXSwiYW1iZXJfdGNiX3N0YXR1cyI6Ik9LIiwiYW1iZXJfZXZpZGVuY2VfdHlwZSI6IlNHWCIsImFtYmVyX3NpZ25lZF9ub25jZSI6dHJ1ZSwiYW1iZXJfY3VzdG9tX3BvbGljeSI6e30sInZlciI6IjEuMCIsImV4cCI6MTY2NDQ0NzA5MywianRpIjoiMzc5ZjBiMDctNTUzNy00YzdhLWFlNTAtODk2YTU1ZjIzNzY2IiwiaWF0IjoxNjY0NDQ2NzYzLCJpc3MiOiJBUyBBdHRlc3RhdGlvbiBUb2tlbiBJc3N1ZXIifQ.X2UDvraRVzAJpC1G1WAK2Qbx64d9WI5T_AKAq1lK5VAjEf409y5fZPxkBdZ-fGYt653nQ5Ah0-jkFRt0Yo7B2cxNmDWn61mMW9yYtt_55qHcbuDX5x4a-7MVawWjS1gLzY7qddmpzoIhwrx575c5JoQjG4qybDejRufUxhvu_XOOxSfhyh4JGRxBYNX19ZGeIbHtE3mfAXqg6qphZFfClIQLdlU-wGbefyN5mwpTK0T3eQ9Tlt0zZFrcv7lNIAPHHB52Ke9R7qdFEoVNNX-8YFMzk4gQyZdzYJS7Q3ElhQYXhBWnY5iwquftQztQcfydJL8o1OC-Ru0s-keF7OBaxABHcv5OhUKlVc44zaBnekP9lTzRCINYnVK67KxyAHsgXkK19UiX6v1FYxdcmdwZgNn5OkCwxiAMLgB8_CQku6q4aeyhCMo4acD1xKd6kkfgYQDxehLbGV6weT4E60omx6UFE13L9yANNNoWtzy0A4PJsiw0tbRPYYO8ehZ8Vgrb9sc00cdqG7_7ok-iivuxklaaSuzrY8VtkGw9T8g0w__fJ0X2KCMPcl3XfNidhOGxJ9402ff93X-QY3dHyaLOqmtJK0vlQ0vuoThseBSOezETalhFCuh-JUYZskokQ21fDPs2xDiytKubxqzrJVF1G1n1AVNWlIZXPXLyoXANS4s" +) + +func TestVerifyCmd(t *testing.T) { + + os.WriteFile(tokenPath, []byte(token), 0600) + defer os.Remove(tokenPath) + + os.WriteFile(tokenMissingKIDPath, []byte(tokenMissingKID), 0600) + defer os.Remove(tokenMissingKIDPath) + + os.WriteFile(tokenInvalidKIDPath, []byte(tokenInvalidKID), 0600) + defer os.Remove(tokenInvalidKIDPath) + + os.WriteFile(tokenMissingJKUPath, []byte(tokenMissingJKU), 0600) + defer os.Remove(tokenMissingJKUPath) + + os.WriteFile(tokenInvalidJKUPath, []byte(tokenInvalidJKU), 0600) + defer os.Remove(tokenInvalidJKUPath) + + os.WriteFile(tokenMalformedJKUPath, []byte(tokenMalformedJKU), 0600) + defer os.Remove(tokenMalformedJKUPath) + + server := test.MockAmberServer(t) + defer server.Close() + + viper.Set("AMBER_URL", server.URL) + viper.Set("AMBER_API_KEY", "YXBpa2V5") + tt := []struct { + args []string + wantErr bool + description string + }{ + { + args: []string{ + constants.VerifyCmd, + }, + wantErr: true, + description: "Test without inputs", + }, + + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenPath, + }, + wantErr: false, + description: "Test valid token", + }, + + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenMissingKIDPath, + }, + wantErr: true, + description: "Test token with Missing KID Path", + }, + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenInvalidKIDPath, + }, + wantErr: true, + description: "Test token with Invalid KID Path", + }, + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenMissingJKUPath, + }, + wantErr: true, + description: "Test token with missing JKU Path", + }, + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenInvalidJKUPath, + }, + wantErr: true, + description: "Test token with Invalid JKU Path", + }, + { + args: []string{ + constants.VerifyCmd, + "--" + constants.VerifyTokenOption, + tokenMalformedJKUPath, + }, + wantErr: true, + description: "Test token with Invalid JKU Path", + }, + } + + for _, tc := range tt { + _, err := execute(t, rootCmd, tc.args...) + + if tc.wantErr == true { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + } +} + +func TestVerifyCmd_MissingAmberUrl(t *testing.T) { + + viper.Set("AMBER_URL", "") + viper.Set("AMBER_API_KEY", "YXBpa2V5") + _, err := execute(t, rootCmd, constants.VerifyCmd) + assert.Error(t, err) +} + +func TestVerifyCmd_MissingAmberApiKey(t *testing.T) { + + server := test.MockAmberServer(t) + defer server.Close() + + viper.Set("AMBER_URL", server.URL) + viper.Set("AMBER_API_KEY", "") + _, err := execute(t, rootCmd, constants.VerifyCmd) + assert.Error(t, err) +} + +func TestVerifyCmd_MalformedAmberUrl(t *testing.T) { + + viper.Set("AMBER_URL", ":amber.com") + viper.Set("AMBER_API_KEY", "YXBpa2V5") + _, err := execute(t, rootCmd, constants.VerifyCmd) + assert.Error(t, err) +} + +func TestVerifyCmd_MalformedAmberApiKey(t *testing.T) { + + server := test.MockAmberServer(t) + defer server.Close() + + viper.Set("AMBER_URL", server.URL) + viper.Set("AMBER_API_KEY", "@p!key") + _, err := execute(t, rootCmd, constants.VerifyCmd) + assert.Error(t, err) +} diff --git a/amber-cli-tdx/constants/constants.go b/amber-cli-tdx/constants/constants.go index 3ec4ea6..03562d2 100644 --- a/amber-cli-tdx/constants/constants.go +++ b/amber-cli-tdx/constants/constants.go @@ -22,6 +22,7 @@ const ( TokenCmd = "token" RootCmd = "amber-cli" VersionCmd = "version" + VerifyCmd = "verify" ) // Options Names @@ -33,6 +34,7 @@ const ( InputOption = "in" UserDataOption = "user-data" NonceOption = "nonce" + VerifyTokenOption = "token-path" ) const ( diff --git a/go-tdx/README.md b/go-tdx/README.md index 50e3250..941e6ec 100644 --- a/go-tdx/README.md +++ b/go-tdx/README.md @@ -1,15 +1,5 @@ # Intel Project Amber Go TDX Adapter -This is the beta version of Go TDX Adapter for collecting Quote from TDX enabled platform. - -This library leverages Intel SGX DCAP for Quote generation: [https://github.com/intel/SGXDataCenterAttestationPrimitives](https://github.com/intel/SGXDataCenterAttestationPrimitives) - -## Installation - -Install the latest version of the library with the following commands: - -```sh -go get github.com/intel/amber-client/go-tdx -``` +This is the beta version of Go TDX Azure Adapter for collecting Quote from TDX enabled platform. ## Go Requirement @@ -24,7 +14,7 @@ collect quote from TDX enabled platform. import "github.com/intel/amber-client/go-tdx" evLogParser := tdx.NewEventLogParser() -adapter, err := tdx.NewAdapter(tdHeldData, evLogParser) +adapter, err := tdx.NewAzureAdapter(tdHeldData, evLogParser) if err != nil { return err } diff --git a/go-tdx/azure_adapter.go b/go-tdx/azure_adapter.go new file mode 100644 index 0000000..3b39b1d --- /dev/null +++ b/go-tdx/azure_adapter.go @@ -0,0 +1,171 @@ +//go:build !test + +/* + * Copyright (c) 2023 Intel Corporation + * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +package tdx + +import ( + "bytes" + "crypto/sha512" + "encoding/base64" + "encoding/json" + "io" + "net/http" + "syscall" + "unsafe" + + "github.com/intel/amber/v1/client" + "github.com/pkg/errors" +) + +// AzureAdapter manages TDX Quote collection from Azure enabled platform +type AzureAdapter struct { + uData []byte + EvLogParser EventLogParser +} + +// NewAzureAdapter returns a new Azure Adapter instance +func NewAzureAdapter(udata []byte, evLogParser EventLogParser) (*AzureAdapter, error) { + return &AzureAdapter{ + uData: udata, + EvLogParser: evLogParser, + }, nil +} + +type QuoteRequest struct { + Report string `json:"report"` +} + +type QuoteResponse struct { + Quote string `json:"quote"` +} + +func IOC(dir, t, nr, size uintptr) uintptr { + return (dir << IocDirshift) | + (t << IocTypeShift) | + (nr << IocNrShift) | + (size << IocSizeShift) +} + +func IOWR(t, nr, size uintptr) uintptr { + return IOC(IocRead|IocWrite, t, nr, size) +} + +func TdxCmdGetReportIO() uintptr { + return IOWR('T', 1, TdxReportDataLen+TdxReportLen) +} + +// CollectEvidence is used to get TDX quote using Azure Quote Generation service +func (adapter *AzureAdapter) CollectEvidence(nonce []byte) (*client.Evidence, error) { + + hash := sha512.New() + _, err := hash.Write(nonce) + if err != nil { + return nil, err + } + _, err = hash.Write(adapter.uData) + if err != nil { + return nil, err + } + reportData := hash.Sum(nil) + + var tdrequest TdxReportRequest + copy(tdrequest.ReportData[:], []byte(reportData)) + + fd, err := syscall.Open(TdxAttestDevPath, syscall.O_RDWR|syscall.O_SYNC, 0) + if err != nil { + return nil, err + } + defer syscall.Close(fd) + + cmd := TdxCmdGetReportIO() + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&tdrequest))) + if errno != 0 { + return nil, syscall.Errno(errno) + } + + report := make([]byte, TdReportSize) + copy(report, tdrequest.TdReport[:]) + + quote, err := getQuote(report) + if err != nil { + return nil, errors.Errorf("getQuote return error %v", err) + } + + var eventLog []byte + if adapter.EvLogParser != nil { + rtmrEventLogs, err := adapter.EvLogParser.GetEventLogs() + if err != nil { + return nil, errors.Wrap(err, "There was an error while collecting RTMR Event Log Data") + } + + eventLog, err = json.Marshal(rtmrEventLogs) + if err != nil { + return nil, errors.Wrap(err, "Error while marshalling RTMR Event Log Data") + } + } + + return &client.Evidence{ + Type: 1, + Evidence: quote, + UserData: adapter.uData, + EventLog: eventLog, + }, nil +} + +func getQuote(report []byte) ([]byte, error) { + + quoteReq := &QuoteRequest{ + Report: base64.URLEncoding.EncodeToString(report), + } + + body, err := json.Marshal(quoteReq) + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodPost, "http://169.254.169.254/acc/tdquote", bytes.NewReader(body)) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/json") + + httpClient := http.DefaultClient + resp, err := httpClient.Do(req) + if err != nil { + return nil, errors.Wrapf(err, "Request to %q failed", req.URL) + } + + if resp != nil { + defer func() { + err := resp.Body.Close() + if err != nil { + errors.Errorf("Failed to close response body") + } + }() + } + + response, err := io.ReadAll(resp.Body) + if err != nil { + return nil, errors.Errorf("Failed to read response body: %s", err) + } + + if resp.StatusCode != http.StatusOK || resp.ContentLength == 0 { + return nil, errors.Errorf("Request to %q failed: StatusCode = %d, Response = %s", req.URL, resp.StatusCode, string(response)) + } + + var quoteRes QuoteResponse + err = json.Unmarshal(response, "eRes) + if err != nil { + return nil, errors.Wrap(err, "Error unmarshalling Quote response from azure") + } + + quote, err := base64.RawURLEncoding.DecodeString(quoteRes.Quote) + if err != nil { + return nil, errors.Wrap(err, "Error decoding Quote from azure") + } + return quote, nil +} diff --git a/go-tdx/collect_evidence.go b/go-tdx/collect_evidence.go deleted file mode 100644 index 989b2e9..0000000 --- a/go-tdx/collect_evidence.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build !test - -/* - * Copyright (c) 2022 Intel Corporation - * All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ -package tdx - -// #cgo CFLAGS: -fstack-protector-strong -// #cgo LDFLAGS: -ltdx_attest -L/usr/lib/x86_64-linux-gnu/ -// -// #include -// #include "tdx_attest.h" -import "C" -import ( - "crypto/sha512" - "encoding/json" - "unsafe" - - "github.com/intel/amber/v1/client" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" -) - -// CollectEvidence is used to get TDX quote using DCAP Quote Generation service -func (adapter *TdxAdapter) CollectEvidence(nonce []byte) (*client.Evidence, error) { - - hash := sha512.New() - _, err := hash.Write(nonce) - if err != nil { - return nil, err - } - _, err = hash.Write(adapter.uData) - if err != nil { - return nil, err - } - reportData := hash.Sum(nil) - - cReportData := [64]C.uint8_t{} - for i := 0; i < len(reportData); i++ { - cReportData[i] = C.uint8_t(reportData[i]) - } - - // tdxReportData holds the reportdata provided as input from attested app - tdxReportData := &C.tdx_report_data_t{d: cReportData} - - // selectedAttKeyId holds the default key id used for generating quote - var selectedAttKeyId C.tdx_uuid_t - - var quoteSize C.uint32_t - var quoteBuf *C.uint8_t - - ret := C.tdx_att_get_quote(tdxReportData, nil, 0, &selectedAttKeyId, "eBuf, "eSize, 0) - if ret != 0 { - return nil, errors.Errorf("tdx_att_get_quote return error code %x", ret) - } - - quote := C.GoBytes(unsafe.Pointer(quoteBuf), C.int(quoteSize)) - - ret = C.tdx_att_free_quote(quoteBuf) - if ret != 0 { - log.Warnf("tdx_att_free_quote return error code %x", ret) - } - - var eventLog []byte - if adapter.EvLogParser != nil { - rtmrEventLogs, err := adapter.EvLogParser.GetEventLogs() - if err != nil { - return nil, errors.Wrap(err, "There was an error while collecting RTMR Event Log Data") - } - - eventLog, err = json.Marshal(rtmrEventLogs) - if err != nil { - return nil, errors.Wrap(err, "Error while marshalling RTMR Event Log Data") - } - } - - return &client.Evidence{ - Type: 1, - Evidence: quote, - UserData: adapter.uData, - EventLog: eventLog, - }, nil -} diff --git a/go-tdx/constants.go b/go-tdx/constants.go new file mode 100644 index 0000000..c8c8cbf --- /dev/null +++ b/go-tdx/constants.go @@ -0,0 +1,37 @@ +//go:build !test + +/* + * Copyright (c) 2023 Intel Corporation + * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +package tdx + +const ( + TdxReportDataLen = 64 + TdxReportLen = 1024 + TdxAttestDevPath = "/dev/tdx_guest" + + TdxGetReportSuccess = 0 + TdxGetReportFailed = -1 + + TdReportSize = 1024 + TdQuoteMaxSize = 8192 +) + +type TdxReportRequest struct { + ReportData [TdxReportDataLen]byte + TdReport [TdxReportLen]byte +} + +const ( + IocNrBits = 8 + IocTypeBits = 8 + IocSizeBits = 14 + IocNrShift = 0 + IocWrite uintptr = 1 + IocRead uintptr = 2 + IocTypeShift = IocNrShift + IocNrBits + IocSizeShift = IocTypeShift + IocTypeBits + IocDirshift = IocSizeShift + IocSizeBits +) diff --git a/go-tdx/mock_adapter.go b/go-tdx/mock_adapter.go index ce26f37..f54b645 100644 --- a/go-tdx/mock_adapter.go +++ b/go-tdx/mock_adapter.go @@ -17,14 +17,14 @@ type MockTdxAdapter struct { EvLogParser EventLogParser } -func NewAdapter(udata []byte, evLogParser EventLogParser) (*MockTdxAdapter, error) { +func NewAzureAdapter(udata []byte, evLogParser EventLogParser) (*MockTdxAdapter, error) { return &MockTdxAdapter{ uData: udata, EvLogParser: evLogParser, }, nil } -// CollectEvidence is used to get TDX quote using DCAP Quote Generation service +// CollectEvidence returns mock Evidence func (adapter *MockTdxAdapter) CollectEvidence(nonce []byte) (*client.Evidence, error) { return &client.Evidence{ diff --git a/go-tdx/tdx_adapter.go b/go-tdx/tdx_adapter.go deleted file mode 100644 index e228fb8..0000000 --- a/go-tdx/tdx_adapter.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build !test - -/* - * Copyright (c) 2022 Intel Corporation - * All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ -package tdx - -// TdxAdapter manages TDX Quote collection from TDX enabled platform -type TdxAdapter struct { - uData []byte - EvLogParser EventLogParser -} - -// NewAdapter returns a new TDX Adapter instance -func NewAdapter(udata []byte, evLogParser EventLogParser) (*TdxAdapter, error) { - return &TdxAdapter{ - uData: udata, - EvLogParser: evLogParser, - }, nil -}