def remove_signer(cmd, client, signer=None, signer_file=None, resource_group_name=None, provider_name=None): if not signer and not signer_file: raise CLIError( 'Please specify one of parameters: --signer or --signer-file/-f') if signer and signer_file: raise CLIError('--signer and --signer-file/-f are mutually exclusive.') if signer_file: signer_file = os.path.expanduser(signer_file) if not os.path.exists(signer_file): raise CLIError( 'Signer file "{}" does not exist.'.format(signer_file)) if not os.path.isfile(signer_file): raise CLIError('Signer file "{}" is not a valid file name.'.format( signer_file)) with open(signer_file) as f: signer = f.read() provider_client = cf_attestation_provider(cmd.cli_ctx) provider = provider_client.get(resource_group_name=resource_group_name, provider_name=provider_name) client.remove(tenant_base_url=provider.attest_uri, policy_certificate_to_remove=signer) return list_signers(cmd, client, resource_group_name, provider_name)
def repo_creds(username, encrypted_password, has_pass): """Get a representation of the container repository credentials""" from azure.servicefabric.models import RegistryCredential from getpass import getpass # Wonky since we allow empty string as an encrypted passphrase if not any([username, encrypted_password is not None, has_pass]): return None if (encrypted_password is not None) and (not username): raise CLIError('Missing container repository username') if has_pass and (not username): raise CLIError('Missing container repository username') if encrypted_password is not None: return RegistryCredential(registry_user_name=username, registry_password=encrypted_password, password_encrypted=True) if has_pass: passphrase = getpass(prompt='Container repository password: ') return RegistryCredential(registry_user_name=username, registry_password=passphrase, password_encrypted=False) return RegistryCredential(registry_user_name=username)
def validate_provider_resource_id(ns): resource_id = getattr(ns, 'identifier', None) if resource_id: if ns.resource_group_name or ns.provider_name: raise CLIError( 'Please omit --resource-group/-g or --name/-n if you have already specified --id.' ) ns.resource_group_name = resource_id.split('/')[4] ns.provider_name = resource_id.split('/')[8] if not all([ns.resource_group_name, ns.provider_name]): raise CLIError( 'Please specify both --resource-group/-g and --name/-n.') del ns.identifier
def read_file(file_path): """Reads a file contents given a file path""" file_contents = None with open(file_path) as f_desc: file_contents = f_desc.read() if not file_contents: raise CLIError('Could not read {}'.format(file_path)) return file_contents
def add_signer(cmd, client, signer=None, signer_file=None, resource_group_name=None, provider_name=None): if not signer and not signer_file: raise CLIError( 'Please specify one of parameters: --signer or --signer-file/-f') if signer and signer_file: raise CLIError('--signer and --signer-file/-f are mutually exclusive.') if signer_file: signer_file = os.path.expanduser(signer_file) if not os.path.exists(signer_file): raise CLIError( 'Signer file "{}" does not exist.'.format(signer_file)) if not os.path.isfile(signer_file): raise CLIError('Signer file "{}" is not a valid file name.'.format( signer_file)) with open(signer_file) as f: signer = f.read() provider_client = cf_attestation_provider(cmd.cli_ctx) provider = provider_client.get(resource_group_name=resource_group_name, provider_name=provider_name) token = client.add(tenant_base_url=provider.attest_uri, policy_certificate_to_add=signer) result = {'Jwt': token} if token: header = jwt.get_unverified_header(token) result.update({ 'Algorithm': header.get('alg', ''), 'JKU': header.get('jku', '') }) body = jwt.decode(token, algorithms=['RS256'], options={"verify_signature": False}) result['Certificates'] = body.get('aas-policyCertificates', {}).get('keys', []) result['CertificateCount'] = len(result['Certificates']) return result
def login(scopes: str, client_id=None, tenant_id=None): # Stripping whitespaces so that users don't have to worry about how # they enter scopes. ie "user.read, mail.read" or "user.read,mail.read" scopes = [scope.strip() for scope in scopes.split(',')] logged_in = authentication.login(scopes, client_id, tenant_id) if not logged_in: raise CLIError('Login failed') print('Logged in successfully')
def attestation_attestation_provider_create(client, resource_group_name, provider_name, location, tags=None, certs_input_path=None): certs = [] if not certs_input_path: certs_input_path = [] for p in certs_input_path: expand_path = os.path.expanduser(p) if not os.path.exists(expand_path): raise CLIError('Path "{}" does not exist.'.format(expand_path)) if not os.path.isfile(expand_path): raise CLIError( '"{}" is not a valid file path.'.format(expand_path)) with open(expand_path, 'rb') as f: pem_data = f.read() cert = load_pem_x509_certificate(pem_data, backend=default_backend()) key = cert.public_key() if isinstance(key, rsa.RSAPublicKey): kty = 'RSA' alg = 'RS256' else: raise CLIError('Unsupported key type: {}'.format(type(key))) jwk = JsonWebKey(kty=kty, alg=alg, use='sig') jwk.x5c = [ base64.b64encode(cert.public_bytes(Encoding.DER)).decode('ascii') ] certs.append(jwk) return client.create(resource_group_name=resource_group_name, provider_name=provider_name, location=location, tags=tags, certs=certs)
def _get_endpoint(self): host_name = None https_prefix = "https://" http_prefix = "http://" if self.name.lower().startswith(https_prefix): self.name = self.name[len(https_prefix):] elif self.name.lower().startswith(http_prefix): self.name = self.name[len(http_prefix):] if not all([valid_hostname(self.name), "." in self.name]): instance = self.rp.find_instance(name=self.name, resource_group_name=self.rg) host_name = instance.host_name if not host_name: raise CLIError("Instance has invalid hostName. Aborting operation...") else: host_name = self.name return "https://{}".format(host_name)
def set_policy(cmd, client, attestation_type, new_attestation_policy=None, new_attestation_policy_file=None, policy_format='Text', resource_group_name=None, provider_name=None): if new_attestation_policy_file and new_attestation_policy: raise CLIError( 'Please specify just one of --new-attestation-policy and --new-attestation-policy-file/-f' ) if not new_attestation_policy_file and not new_attestation_policy: raise CLIError( 'Please specify --new-attestation-policy or --new-attestation-policy-file/-f' ) if new_attestation_policy_file: file_path = os.path.expanduser(new_attestation_policy_file) if not os.path.exists(file_path): raise CLIError( 'Policy file "{}" does not exist.'.format(file_path)) if not os.path.isfile(file_path): raise CLIError('"{}" is not a valid file name.'.format(file_path)) with open(file_path) as f: new_attestation_policy = f.read() provider_client = cf_attestation_provider(cmd.cli_ctx) provider = provider_client.get(resource_group_name=resource_group_name, provider_name=provider_name) if policy_format == 'Text': if provider.trust_model != 'AAD': raise CLIError( 'Only supports Text policy under AAD model. Current model: {}. ' 'If you are using signed JWT policy, please specify --policy-format JWT' .format(provider.trust_model)) import jwt try: new_attestation_policy = \ base64.urlsafe_b64encode(new_attestation_policy.encode('ascii')).decode('ascii').strip('=') new_attestation_policy = { 'AttestationPolicy': new_attestation_policy } new_attestation_policy = jwt.encode(new_attestation_policy, key='', algorithm='none') except TypeError as e: print(e) raise CLIError( 'Failed to encode text content, are you using JWT? If yes, please use --policy-format JWT' ) client.set(tenant_base_url=provider.attest_uri, tee=tee_mapping[attestation_type], new_attestation_policy=new_attestation_policy) return get_policy(cmd, client, attestation_type, resource_group_name=resource_group_name, provider_name=provider_name)
def profile_exception_handler(exception): raise CLIError(exception)
def auth_exception_handler(exception): raise CLIError(exception)
def attest_open_enclave(self, tenant_base_url, request, custom_headers=None, raw=False, **operation_config): """Attest to an SGX-OpenEnclaveSDK enclave. """ url = '/attest/OpenEnclave' path_format_arguments = { 'tenantBaseUrl': self._serialize.url("tenant_base_url", tenant_base_url, 'str', skip_quote=True) } url = self._client.format_url(url, **path_format_arguments) # Construct parameters query_parameters = {} query_parameters['api-version'] = self._serialize.query( "self.api_version", self.api_version, 'str') # Construct headers header_parameters = {} header_parameters['Accept'] = 'application/json' header_parameters['Content-Type'] = 'text/plain' if self.config.generate_client_request_id: header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: header_parameters['accept-language'] = self._serialize.header( "self.config.accept_language", self.config.accept_language, 'str') # Construct body body_content = self._serialize.body(request, 'AttestOpenEnclaveRequest') # Construct and send request request = self._client.post(url, query_parameters, header_parameters, body_content) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200, 400, 401]: exp = CloudError(response) exp.request_id = response.headers.get('x-ms-request-id') raise exp deserialized = None if response.status_code == 400: raise CLIError(response.text) if response.status_code == 401: deserialized = self._deserialize('str', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized
def remove( self, tenant_base_url, policy_certificate_to_remove, custom_headers=None, raw=False, **operation_config): """Removes the specified policy management certificate. Note that the final policy management certificate cannot be removed. :param tenant_base_url: The tenant name, for example https://mytenant.attest.azure.net. :type tenant_base_url: str :param policy_certificate_to_remove: An RFC7519 JSON Web Token containing a claim named "maa-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 :type policy_certificate_to_remove: str :param dict custom_headers: headers that will be added to the request :param bool raw: returns the direct response alongside the deserialized response :param operation_config: :ref:`Operation configuration overrides<msrest:optionsforoperations>`. :return: object or ClientRawResponse if raw=true :rtype: object or ~msrest.pipeline.ClientRawResponse :raises: :class:`CloudError<msrestazure.azure_exceptions.CloudError>` """ # Construct URL url = self.remove.metadata['url'] path_format_arguments = { 'tenantBaseUrl': self._serialize.url("tenant_base_url", tenant_base_url, 'str', skip_quote=True) } url = self._client.format_url(url, **path_format_arguments) # Construct parameters query_parameters = {} query_parameters['api-version'] = self._serialize.query("self.api_version", self.api_version, 'str') # query_parameters['api-version'] = '2018-09-01-preview' # Construct headers header_parameters = {} header_parameters['Accept'] = 'application/json' header_parameters['Content-Type'] = 'application/json; charset=utf-8' if self.config.generate_client_request_id: header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct body body_content = self._serialize.body(policy_certificate_to_remove, 'str') # Construct and send request request = self._client.post(url, query_parameters, header_parameters, body_content) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200, 400, 401]: exp = CloudError(response) exp.request_id = response.headers.get('x-ms-request-id') raise exp deserialized = None if response.status_code == 200: deserialized = self._deserialize('str', response) if response.status_code == 400: raise CLIError(response.text) if response.status_code == 401: deserialized = self._deserialize('str', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized
def reset( self, tenant_base_url, tee, policy_jws, custom_headers=None, raw=False, **operation_config): """Resets the attestation policy for the specified tenant and reverts to the default policy. :param tenant_base_url: The tenant name, for example https://mytenant.attest.azure.net. :type tenant_base_url: str :param tee: Specifies the trusted execution environment to be used to validate the evidence. Possible values include: 'SgxEnclave', 'OpenEnclave', 'CyResComponent', 'VSMEnclave' :type tee: str or ~azure.attestation.models.TeeKind :param policy_jws: JSON Web Signature with an empty policy document :type policy_jws: str :param dict custom_headers: headers that will be added to the request :param bool raw: returns the direct response alongside the deserialized response :param operation_config: :ref:`Operation configuration overrides<msrest:optionsforoperations>`. :return: object or ClientRawResponse if raw=true :rtype: object or ~msrest.pipeline.ClientRawResponse :raises: :class:`CloudError<msrestazure.azure_exceptions.CloudError>` """ # Construct URL url = '/policies/{}%3areset'.format(tee) path_format_arguments = { 'tenantBaseUrl': self._serialize.url("tenant_base_url", tenant_base_url, 'str', skip_quote=True) } url = self._client.format_url(url, **path_format_arguments) # Construct parameters query_parameters = {} query_parameters['api-version'] = self._serialize.query("self.api_version", self.api_version, 'str') query_parameters['tee'] = self._serialize.query("tee", tee, 'str') # Construct headers header_parameters = {} header_parameters['Accept'] = 'application/json' header_parameters['Content-Type'] = 'text/plain' if self.config.generate_client_request_id: header_parameters['x-ms-client-request-id'] = str(uuid.uuid1()) if custom_headers: header_parameters.update(custom_headers) if self.config.accept_language is not None: header_parameters['accept-language'] = self._serialize.header("self.config.accept_language", self.config.accept_language, 'str') # Construct body body_content = self._serialize.body(policy_jws, 'str') # Construct and send request request = self._client.post(url, query_parameters, header_parameters, body_content) response = self._client.send(request, stream=False, **operation_config) if response.status_code not in [200, 400, 401]: exp = CloudError(response) exp.request_id = response.headers.get('x-ms-request-id') raise exp deserialized = None if response.status_code == 200: deserialized = self._deserialize('str', response) if response.status_code == 400: raise CLIError(response.text) if response.status_code == 401: deserialized = self._deserialize('str', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) return client_raw_response return deserialized
def _get_endpoint(self): instance = self.rp.find_instance(name=self.name, resource_group_name=self.rg) host_name = instance.host_name if not host_name: raise CLIError("Retrieved hostName was null which is invalid.") return "https://{}".format(instance.host_name)