Skip to content

Commit

Permalink
[Attestation] Add data-plane operations (Azure#1978)
Browse files Browse the repository at this point in the history
  • Loading branch information
bim-msft authored Aug 19, 2020
1 parent 1a8ba5b commit d5348f0
Show file tree
Hide file tree
Showing 26 changed files with 1,961 additions and 156 deletions.
53 changes: 53 additions & 0 deletions src/attestation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,57 @@ az attestation delete \
--resource-group "MyResourceGroup"
```

#### Add a new attestation policy certificate ####
Example:
```
az attestation signer add \
-n "myattestationprovider" -g "MyResourceGroup" \
--signer "eyAiYWxnIjoiUlMyNTYiLCAie..."
```

#### Remove the specified policy management certificate ####
Example:
```
az attestation signer remove \
-n "myattestationprovider" -g "MyResourceGroup" \
--signer "eyAiYWxnIjoiUlMyNTYiLCAie..."
```

#### Retrieve the set of certificates used to express policy ####
Example:
```
az attestation signer list \
-n "myattestationprovider" -g "MyResourceGroup"
```

#### Set the policy for a given kind of TEE ####
Note: You need to specify `-n` and `-g` (or use `-u`) even if they are not marked as `required` parameters.

Example:
```
az attestation policy set \
-n "myattestationprovider" -g "MyResourceGroup" \
--tee SgxEnclave --new-attestation-policy "newAttestationPolicyname"
az attestation policy set \
-u https://myattestationprovider.eastus2.attest.azure.net \
--tee SgxEnclave --new-attestation-policy "newAttestationPolicyname"
```

#### Reset the attestation policy ####
Example:
```
az attestation policy reset \
-n "myattestationprovider" -g "MyResourceGroup" \
--tee SgxEnclave --policy-jws "eyJhbGciOiJub25lIn0.."
```

#### Retrieve the current policy for a given kind of TEE. ####
Example:
```
az attestation policy show \
-n "myattestationprovider" -g "MyResourceGroup" \
--tee SgxEnclave
```

If you have issues, please give feedback by opening an issue at https://github.com/Azure/azure-cli-extensions/issues.
4 changes: 2 additions & 2 deletions src/attestation/azext_attestation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class AttestationManagementClientCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType
from azext_attestation.generated._client_factory import cf_attestation
from azext_attestation.generated._client_factory import cf_attestation_mgmt
attestation_custom = CliCommandType(
operations_tmpl='azext_attestation.custom#{}',
client_factory=cf_attestation)
client_factory=cf_attestation_mgmt)
super(AttestationManagementClientCommandsLoader, self).__init__(cli_ctx=cli_ctx,
custom_command_type=attestation_custom)

Expand Down
30 changes: 28 additions & 2 deletions src/attestation/azext_attestation/generated/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,37 @@
# --------------------------------------------------------------------------


def cf_attestation(cli_ctx, *_):
def cf_attestation_mgmt(cli_ctx, *_):
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from ..vendored_sdks.azure_mgmt_attestation import AttestationManagementClient
return get_mgmt_service_client(cli_ctx, AttestationManagementClient)


def cf_attestation_provider(cli_ctx, *_):
return cf_attestation(cli_ctx).attestation_provider
return cf_attestation_mgmt(cli_ctx).attestation_provider


def cf_attestation_data(cli_ctx, *_):
from ..vendored_sdks.azure_attestation import AttestationClient
from azure.cli.core._profile import Profile

profile = Profile(cli_ctx=cli_ctx)
cred, _, _ = profile.get_login_credentials(
resource="https://attest.azure.net")
return AttestationClient(credentials=cred)


def cf_policy(cli_ctx, *_):
return cf_attestation_data(cli_ctx).policy


def cf_policy_certificates(cli_ctx, *_):
return cf_attestation_data(cli_ctx).policy_certificates


def cf_signing_certificates(cli_ctx, *_):
return cf_attestation_data(cli_ctx).signing_certificates


def cf_metadata_configuration(cli_ctx, *_):
return cf_attestation_data(cli_ctx).metadata_configuration
69 changes: 69 additions & 0 deletions src/attestation/azext_attestation/generated/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,72 @@
text: |-
az attestation delete --name "myattestationprovider" --resource-group "MyResourceGroup"
"""

helps['attestation policy'] = """
type: group
short-summary: Manage the policies
"""

helps['attestation policy set'] = """
type: command
short-summary: Sets the policy for a given kind of TEE.
examples:
- name: Sets the policy for a given kind of TEE (SgxEnclave).
text: |-
az attestation policy set -n "myattestationprovider" -g "MyResourceGroup" --tee SgxEnclave \\
--new-attestation-policy "newAttestationPolicyname"
"""

helps['attestation policy reset'] = """
type: command
short-summary: Resets the attestation policy for the specified tenant and reverts to the default policy.
examples:
- name: Resets the attestation policy for the specified tenant and reverts to the default policy.
text: |-
az attestation policy reset -n "myattestationprovider" -g "MyResourceGroup" --tee SgxEnclave \\
--policy-jws "eyJhbGciOiJub25lIn0.."
"""

helps['attestation policy show'] = """
type: command
short-summary: Retrieves the current policy for a given kind of TEE.
examples:
- name: Retrieves the current policy for a given kind of TEE (SgxEnclave).
text: |-
az attestation policy show -n "myattestationprovider" -g "MyResourceGroup" --tee SgxEnclave
"""

helps['attestation signer'] = """
type: group
short-summary: Manage the trusted policy signers
"""

helps['attestation signer add'] = """
type: command
short-summary: Adds a new attestation policy certificate to the set of policy management certificates.
examples:
- name: Adds a new attestation policy certificate to the set of policy management certificates.
text: |-
az attestation signer add -n "myattestationprovider" -g "MyResourceGroup" \\
--signer "eyAiYWxnIjoiUlMyNTYiLCAie..."
"""

helps['attestation signer remove'] = """
type: command
short-summary: Removes the specified policy management certificate. Note that the final policy management
certificate cannot be removed.
examples:
- name: Removes the specified policy management certificate.
text: |-
az attestation signer remove -n "myattestationprovider" -g "MyResourceGroup" \\
--signer "eyAiYWxnIjoiUlMyNTYiLCAie..."
"""

helps['attestation signer list'] = """
type: command
short-summary: Retrieves the set of certificates used to express policy for the current tenant.
examples:
- name: Retrieves the set of certificates used to express policy for the current tenant.
text: |-
az attestation signer list -n "myattestationprovider" -g "MyResourceGroup"
"""
36 changes: 35 additions & 1 deletion src/attestation/azext_attestation/generated/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@
tags_type,
resource_group_name_type,
get_location_type,
file_type
file_type,
get_resource_name_completion_list,
get_enum_type
)
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from knack.arguments import CLIArgumentType


def load_arguments(self, _):
from ..vendored_sdks.azure_attestation.models import TeeKind

attestation_name_type = CLIArgumentType(
help='Name of the attestation.', options_list=['--name', '-n'], metavar='NAME', id_part=None,
completer=get_resource_name_completion_list('Microsoft.Attestation/attestationProviders'))

with self.argument_context('attestation list') as c:
c.argument('resource_group_name', resource_group_name_type)
Expand All @@ -44,3 +52,29 @@ def load_arguments(self, _):
c.argument('resource_group_name', resource_group_name_type)
c.argument('provider_name', options_list=['--name', '-n'], help='Name of the attestation service',
id_part='name')

for item in ['list', 'add', 'remove']:
with self.argument_context('attestation signer {}'.format(item)) as c:
c.extra('resource_group_name', resource_group_name_type, required=False)
c.extra('attestation_name', attestation_name_type, required=False)
c.argument('tenant_base_url', options_list=['--attestation-base-url', '-u'], required=False,
help='URL of the attestation, for example: https://myatt.eus2.attest.azure.net. '
'You can ignore --name and --resource-group if you specified the URL.')
if item in ['add', 'remove']:
c.argument('policy_certificate_to_{}'.format(item), options_list=['--signer'],
help='The policy certificate to {}. An RFC7519 JSON Web Token containing a claim named '
'"aas-policyCertificate" whose value is an RFC7517 JSON Web Key which specifies a '
'new key to update. The RFC7519 JWT must be signed with one of the existing signing '
'certificates'.format(item))

for item in ['set', 'reset', 'show']:
with self.argument_context('attestation policy {}'.format(item)) as c:
c.extra('resource_group_name', resource_group_name_type, required=False)
c.extra('attestation_name', attestation_name_type, required=False)
c.argument('tenant_base_url', options_list=['--attestation-base-url', '-u'], required=False,
help='URL of the attestation, for example: https://myatt.eus2.attest.azure.net. '
'You can ignore --name and --resource-group if you specified the URL.')
c.argument('tee', arg_type=get_enum_type(TeeKind))

with self.argument_context('attestation policy set') as c:
c.argument('new_attestation_policy', options_list=['--new-attestation-policy', '-p'])
16 changes: 16 additions & 0 deletions src/attestation/azext_attestation/generated/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,19 @@
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------

from knack.util import CLIError

from ._client_factory import cf_attestation_provider


def validate_attestation_name(cmd, ns):
if not ns.tenant_base_url:
if ns.attestation_name and ns.resource_group_name:
provider = cf_attestation_provider(cmd.cli_ctx).\
get(provider_name=ns.attestation_name, resource_group_name=ns.resource_group_name)
ns.tenant_base_url = provider.attest_uri
del ns.attestation_name
del ns.resource_group_name
else:
raise CLIError('incorrect usage: [--attestation-base-url | --name/-n --resource-group-name/-g]')
49 changes: 41 additions & 8 deletions src/attestation/azext_attestation/generated/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,51 @@

from azure.cli.core.commands import CliCommandType

from ._validators import validate_attestation_name


def load_command_table(self, _):
from ._client_factory import cf_attestation_provider, cf_policy_certificates, cf_policy

from azext_attestation.generated._client_factory import cf_attestation_provider
attestation_attestation_provider = CliCommandType(
operations_tmpl='azext_attestation.vendored_sdks.azure_mgmt_attestation.operations._attestation_provider_opera'
'tions#AttestationProviderOperations.{}',
attestation_provider_mgmt_tmpl = 'azext_attestation.vendored_sdks.azure_mgmt_attestation.operations.' \
'_attestation_provider_operations#AttestationProviderOperations.{}'
attestation_provider_mgmt_sdk = CliCommandType(
operations_tmpl=attestation_provider_mgmt_tmpl,
client_factory=cf_attestation_provider)
with self.command_group('attestation', attestation_attestation_provider,
client_factory=cf_attestation_provider, is_experimental=True) as g:

policy_certificates_data_tmpl = 'azext_attestation.vendored_sdks.azure_attestation.operations.' \
'_policy_certificates_operations#PolicyCertificatesOperations.{}'
policy_certificates_data_sdk = CliCommandType(
operations_tmpl=policy_certificates_data_tmpl,
client_factory=cf_policy_certificates)

policy_data_tmpl = 'azext_attestation.vendored_sdks.azure_attestation.operations.' \
'_policy_operations#PolicyOperations.{}'
policy_data_sdk = CliCommandType(
operations_tmpl=policy_data_tmpl,
client_factory=cf_policy)

with self.command_group('attestation', attestation_provider_mgmt_sdk, client_factory=cf_attestation_provider,
is_experimental=True) as g:
g.custom_command('list', 'attestation_attestation_provider_list')
g.custom_show_command('show', 'attestation_attestation_provider_show')
g.custom_command('create', 'attestation_attestation_provider_create')
g.custom_command(
'delete', 'attestation_attestation_provider_delete', confirmation=True)
g.custom_command('delete', 'attestation_attestation_provider_delete', confirmation=True)

with self.command_group('attestation signer', policy_certificates_data_sdk, client_factory=cf_policy_certificates,
is_experimental=True) as g:
g.command('add', 'add', validator=validate_attestation_name,
doc_string_source=policy_certificates_data_tmpl.format('add'))
g.command('remove', 'remove', validator=validate_attestation_name,
doc_string_source=policy_certificates_data_tmpl.format('remove'))
g.custom_command('list', 'list_signers', validator=validate_attestation_name,
doc_string_source=policy_certificates_data_tmpl.format('get'))

with self.command_group('attestation policy', policy_data_sdk, client_factory=cf_policy,
is_experimental=True) as g:
g.command('set', 'set', validator=validate_attestation_name,
doc_string_source=policy_data_tmpl.format('set'))
g.command('reset', 'reset', validator=validate_attestation_name,
doc_string_source=policy_data_tmpl.format('reset'))
g.custom_command('show', 'get_policy', validator=validate_attestation_name,
doc_string_source=policy_data_tmpl.format('get'))
38 changes: 29 additions & 9 deletions src/attestation/azext_attestation/generated/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,34 @@
# --------------------------------------------------------------------------
# pylint: disable=too-many-lines

import jwt

from knack.util import CLIError


def attestation_attestation_provider_list(cmd, client,
resource_group_name=None):
def attestation_attestation_provider_list(client, resource_group_name=None):
if resource_group_name:
return client.list_by_resource_group(resource_group_name=resource_group_name)
return client.list()
return client.list_by_resource_group(resource_group_name=resource_group_name).value
return client.list().value


def attestation_attestation_provider_show(cmd, client,
def attestation_attestation_provider_show(client,
resource_group_name,
provider_name):
return client.get(resource_group_name=resource_group_name,
provider_name=provider_name)


def attestation_attestation_provider_create(cmd, client,
def attestation_attestation_provider_create(client,
resource_group_name,
provider_name,
location=None,
tags=None,
attestation_policy=None,
certs_input_path=None):
certs = parse_pem(certs_input_path)
certs = []
if certs_input_path:
certs = parse_pem(certs_input_path)
return client.create(resource_group_name=resource_group_name,
provider_name=provider_name,
location=location,
Expand All @@ -42,7 +45,7 @@ def attestation_attestation_provider_create(cmd, client,
keys=certs)


def attestation_attestation_provider_delete(cmd, client,
def attestation_attestation_provider_delete(client,
resource_group_name,
provider_name):
return client.delete(resource_group_name=resource_group_name,
Expand Down Expand Up @@ -81,10 +84,27 @@ def parse_pem(input_file):
if pem_data[i].endswith('\n'):
pem_data[i] = pem_data[i][:-1]
cert += pem_data[i]
print(cert)
certs.append(cert)
start = end + 1
end = start
return certs
except FileNotFoundError as ex:
raise CLIError('File not Found: {}'.format(str(ex)))


def list_signers(client, tenant_base_url, resource_group_name=None, attestation_name=None): # pylint: disable=unused-argument
signers = client.get(tenant_base_url=tenant_base_url)
result = jwt.decode(signers, verify=False)
result['jwt'] = signers
return result


def get_policy(client, tee, tenant_base_url, resource_group_name=None, attestation_name=None): # pylint: disable=unused-argument
raw_result = client.get(tenant_base_url=tenant_base_url, tee=tee).additional_properties['Policy']
result = {}
try:
result = jwt.decode(raw_result, verify=False)
except: # pylint: disable=bare-except
pass
result['jwt'] = raw_result
return result
Loading

0 comments on commit d5348f0

Please sign in to comment.