Skip to content

Commit

Permalink
Merge pull request #68 from NVIDIA/release/1.4.0
Browse files Browse the repository at this point in the history
Release 1.4.0 Changes
  • Loading branch information
rnertney authored Sep 11, 2024
2 parents 16a8033 + 181c253 commit a2854d7
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 109 deletions.
14 changes: 9 additions & 5 deletions guest_tools/attestation_sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The Attestation SDK offers developers easy-to-use APIs for implementing attestat
- [How to do Perform Attestation](#how-to-do-perform-attestation-1)
- [Building Attestation SDK](#building-attestation-sdk)
- [APIs](#apis)
- [End-User License Agreement](#end-user-license-agreement)


## Features
Expand Down Expand Up @@ -53,12 +54,14 @@ If you choose to install the Attestation SDK from the source code instead of a W
- Driver version r535 installed.
- Ensure that the SKU is supported for Confidential Computing.

2. Follow the instructions in nvTrust/guest_tools/local_gpu_verifier/README.md to install the NVIDIA GPU Local Verifier Python SDK.
2. Install Python 3.7 or later.

3. Follow the instructions in nvTrust/guest_tools/local_gpu_verifier/README.md to install the NVIDIA GPU Local Verifier Python SDK.

3. Run the following command and ensure that you have the 'verifier' Python module installed.
4. Run the following command and ensure that you have the 'verifier' Python module installed.
```
pip list | grep verifier
verifier 1.1.0
pip list | grep nv-local-gpu-verifier
nv-local-gpu-verifier 1.4.0
```
### Local GPU Attestation
Expand Down Expand Up @@ -111,5 +114,6 @@ Please refer to the [sample implementation](tests/RemoteGPUTest.py)
| generate_evidence(<-nonce->) | Generate GPU attestation evidence using the Local GPU Verifier Python SDK with a user-provided nonce. |
| verify_evidence(<-nonce->, <-evidence->,<-nras_url->) |Verify the evidence with the NVIDIA Remote Attestation Service (NRAS) |
# End-user License Agreement
By using the Attestation Suite Services, you affirm that you have read the Agreement and agree to its terms. If you do not have the required authority to enter into the Agreement or if you do not accept all Agreement terms and conditions, do not use the Attestation Suite Services. Please see the [End-user License Agreement](https://docs.attestation.nvidia.com/EULA/eula.html) for more information on data collection.
4 changes: 2 additions & 2 deletions guest_tools/attestation_sdk/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "nv-attestation-sdk"
version = "1.3.0"
version = "1.4.0"
authors = [
{name = "NVIDIA"},
]
Expand All @@ -14,7 +14,7 @@ classifiers = [
]
dependencies = [
'pyjwt ~= 2.7.0',
'verifier >= 1.2.0',
'nv-local-gpu-verifier >= 1.2.0',
'requests ~= 2.31.0'
]
keywords = [
Expand Down
76 changes: 58 additions & 18 deletions guest_tools/attestation_sdk/src/nv_attestation_sdk/attestation.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,49 @@ def __new__(cls, name=None):

@classmethod
def set_name(cls, name: str) -> None:
"""Set the name of the Attestation client
Args:
name (str): Attestation client name
"""
cls._name = name

@classmethod
def get_name(cls) -> str:
"""Get the name of the Attestation client
Returns:
str: Attestation client name
"""
return cls._name

@classmethod
def set_nonce_server(cls, url: str) -> None:
"""Set nonce server URL (not used yet)
Args:
url (str): URL of the nonce server
"""
cls._nonceServer = url

@classmethod
def get_nonce_server(cls) -> str:
"""Get the nonce Server URL
Returns:
str: URL of the nonce server
"""
return cls._nonceServer

@classmethod
def add_verifier(cls, dev: Devices, env: Environment, url: str, evidence: str) -> None:
"""
Add a new verifier to SDK configuration.
This will be used during attest and validate_token methods.
"""Add a new verifier for Attestation
Args:
dev (Devices): Type of device to be attestated - GPU, CPU etc.
env (Environment): Type of Attestation - local, remote etc.
url (str): URL of the Attestation Server for Remote Attestation use cases.
evidence (str): Attestation evidence
"""
if (dev == Devices.GPU and env == Environment.LOCAL) :
name = "LOCAL_GPU_CLAIMS"
Expand All @@ -89,26 +113,21 @@ def add_verifier(cls, dev: Devices, env: Environment, url: str, evidence: str) -

@classmethod
def get_verifiers(cls) -> list:
"""
Get the list of configured verifiers.
"""Get a list of configured verifiers
Returns:
list: List of verifiers
"""
return cls._verifiers


@classmethod
def attest(cls) -> bool:
"""Attest the client as per the configured verifiers and evidence policy
Returns:
bool: Attestation Result
"""
Attest the client as per the configured verifiers and evidence policy
"""
# this should consist of doing the following things
# Nonce _generateNonce()
# Evidence generateEvidence(nonce)
# Retrieve quote from vTPM (locally)
# Token verifyEvidence(evidence)
# Evidence -> verifier, validated against policy, returns token
# Status provideEvidence(token)
# Token -> relying party, returns Status
# cls.token = ""
for verifier in cls._verifiers:
attest_result = True

Expand Down Expand Up @@ -147,7 +166,6 @@ def attest(cls) -> bool:

# NOTE: no verifiers means attestation will be true. weird but makes some sense
# NOTE: THIS is where the tokens should be combined in to a single token and then set
#print("full attest_result ... ", attest_result) # NOTE: put a try catch here

eatToken = cls._create_EAT()
cls.set_token( cls._name, eatToken)
Expand Down Expand Up @@ -194,11 +212,25 @@ def _create_EAT(cls) -> str:

@classmethod
def set_token(cls, name: str, eat_token: str) -> None:
"""Set result EAT token for a client
Args:
name (str): Attestation Client name
eat_token (str): EAT token
"""
entry = {name: eat_token}
cls._tokens.update(entry)

@classmethod
def get_token(cls, x=None) -> str:
"""Get the Attestation EAT token for a client
Args:
x (_type_, optional): Client name. Defaults to None.
Returns:
str: EAT token in string format
"""
name = ""
if x == None:
name = cls.get_name()
Expand All @@ -216,6 +248,15 @@ def get_token(cls, x=None) -> str:

@classmethod
def _validate_token_internal(cls, policy:str, eat_token: str) -> bool:
"""Validate a EAT token using the policy
Args:
policy (str): Appraisal policy for Attestation results
eat_token (str): EAT token
Returns:
bool: result
"""
attest_result = True

if eat_token == "":
Expand Down Expand Up @@ -268,7 +309,6 @@ def get_verifier_by_name(cls, verifier_name):

@classmethod
def validate_token(cls, policy:str , x=None) :

if x == None:
name = cls.get_name()
if name == "":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,35 @@
from nv_attestation_sdk import attestation
from urllib.parse import urlparse
from nv_attestation_sdk.gpu import gpu_utils
from ..utils.config import GPU_ARCH, OCSP_SERVICE_URL, RIM_SERVICE_URL, ALLOW_HOLD_CERT


def validate_gpu_token(verifier, gpu_token: str, policy: str):
"""Validate GPU token using a policy
Args:
verifier (_type_): verifier object
gpu_token (str): EAT token
policy (str): Appraisal policy for attestation results
Returns:
bool: result
"""
if policy == "" or gpu_token == "":
return False
decoded_token = jwt.decode(gpu_token, algorithms='HS256', verify=False, key="secret")
auth_rules = gpu_utils.get_auth_rules(policy)
return gpu_utils.validate_gpu_token_with_policy(decoded_token, auth_rules)

def attest(nonce):
"""Attest a device locally
Args:
nonce (str): Nonce as hex string
Returns:
Attestation result and JWT token
"""
attestation_result = False
from verifier import cc_admin
jwt_token = ""
Expand All @@ -30,9 +50,9 @@ def attest(nonce):
"vbios_rim": None,
"user_mode": True,
'rim_root_cert': None,
'rim_service_url': None,
'allow_hold_cert': True,
'ocsp_url': None,
'rim_service_url': RIM_SERVICE_URL,
'allow_hold_cert': ALLOW_HOLD_CERT,
'ocsp_url': OCSP_SERVICE_URL,
'nonce': nonce}
attestation_result, jwt_token = cc_admin.attest(params)
except Exception as e:
Expand All @@ -53,7 +73,7 @@ def build_payload(nonce, evidence, cert_chain):
encoded_evidence = base64.b64encode(encoded_evidence_bytes)
encoded_evidence = encoded_evidence.decode('utf-8')
data['evidence'] = encoded_evidence
data['arch'] = 'HOPPER'
data['arch'] = GPU_ARCH
data['certificate'] = str(cert_chain)
payload = json.dumps(data)
return payload
Expand Down
Loading

0 comments on commit a2854d7

Please sign in to comment.