Exemplo n.º 1
0
 def _azure_interactive_auth(self):
     if self._authentication_record_json is None:
         _interactive_credential = DeviceCodeCredential(
             tenant_id=self._tenant_id,
             timeout=180,
             prompt_callback=None,
             _cache=load_persistent_cache(
                 TokenCachePersistenceOptions(
                     name=self._azure_cred_cache_name,
                     allow_unencrypted_storage=True,
                     cache_location=self._azure_cred_cache_location)))
         _auth_record = _interactive_credential.authenticate()
         self._authentication_record_json = _auth_record.serialize()
     else:
         deserialized_auth_record = AuthenticationRecord.deserialize(
             self._authentication_record_json)
         _interactive_credential = DeviceCodeCredential(
             tenant_id=self._tenant_id,
             timeout=180,
             prompt_callback=None,
             _cache=load_persistent_cache(
                 TokenCachePersistenceOptions(
                     name=self._azure_cred_cache_name,
                     allow_unencrypted_storage=True,
                     cache_location=self._azure_cred_cache_location)),
             authentication_record=deserialized_auth_record)
     return _interactive_credential
Exemplo n.º 2
0
def test_policies_configurable():
    policy = Mock(spec_set=SansIOHTTPPolicy, on_request=Mock())

    transport = validating_transport(
        requests=[Request()] * 3,
        responses=[
            # expected requests: discover tenant, start device code flow, poll for completion
            get_discovery_response(),
            mock_response(
                json_payload={
                    "device_code": "_",
                    "user_code": "user-code",
                    "verification_uri": "verification-uri",
                    "expires_in": 42,
                }
            ),
            mock_response(json_payload=dict(build_aad_response(access_token="**"), scope="scope")),
        ],
    )

    credential = DeviceCodeCredential(
        client_id="client-id", prompt_callback=Mock(), policies=[policy], transport=transport
    )

    credential.get_token("scope")

    assert policy.on_request.called
Exemplo n.º 3
0
def test_user_agent():
    client_id = "client-id"
    transport = validating_transport(
        requests=[Request()] * 2 +
        [Request(required_headers={"User-Agent": USER_AGENT})],
        responses=[
            get_discovery_response(),
            mock_response(
                json_payload={
                    "device_code": "_",
                    "user_code": "user-code",
                    "verification_uri": "verification-uri",
                    "expires_in": 42,
                }),
            mock_response(json_payload=dict(build_aad_response(
                access_token="**", id_token=build_id_token(aud=client_id)),
                                            scope="scope")),
        ],
    )

    credential = DeviceCodeCredential(client_id=client_id,
                                      prompt_callback=Mock(),
                                      transport=transport)

    credential.get_token("scope")
Exemplo n.º 4
0
def test_device_code_credential_timeout():
    transport = validating_transport(
        requests=[Request()] *
        3,  # not validating requests because they're formed by MSAL
        responses=[
            # expected requests: discover tenant, start device code flow, poll for completion
            mock_response(
                json_payload={
                    "authorization_endpoint": "https://a/b",
                    "token_endpoint": "https://a/b"
                }),
            mock_response(json_payload={
                "device_code": "_",
                "user_code": "_",
                "verification_uri": "_"
            }),
            mock_response(json_payload={"error": "authorization_pending"}),
        ],
    )

    credential = DeviceCodeCredential(client_id="_",
                                      prompt_callback=Mock(),
                                      transport=transport,
                                      timeout=0.01,
                                      instance_discovery=False)

    with pytest.raises(ClientAuthenticationError) as ex:
        credential.get_token("scope")
    assert "timed out" in ex.value.message.lower()
def test_device_code_credential():
    client_id = "client-id"
    expected_token = "access-token"
    user_code = "user-code"
    verification_uri = "verification-uri"
    expires_in = 42

    transport = validating_transport(
        requests=[Request()] *
        3,  # not validating requests because they're formed by MSAL
        responses=[
            # expected requests: discover tenant, start device code flow, poll for completion
            mock_response(
                json_payload={
                    "authorization_endpoint": "https://a/b",
                    "token_endpoint": "https://a/b"
                }),
            mock_response(
                json_payload={
                    "device_code": "_",
                    "user_code": user_code,
                    "verification_uri": verification_uri,
                    "expires_in": expires_in,
                }),
            mock_response(json_payload=dict(
                build_aad_response(
                    access_token=expected_token,
                    expires_in=expires_in,
                    refresh_token="_",
                    id_token=build_id_token(aud=client_id),
                ),
                scope="scope",
            ), ),
        ],
    )

    callback = Mock()
    credential = DeviceCodeCredential(
        client_id=client_id,
        prompt_callback=callback,
        transport=transport,
        instance_discovery=False,
        _cache=TokenCache(),
    )

    now = datetime.datetime.utcnow()
    token = credential.get_token("scope")
    assert token.token == expected_token

    # prompt_callback should have been called as documented
    assert callback.call_count == 1
    uri, code, expires_on = callback.call_args[0]
    assert uri == verification_uri
    assert code == user_code

    # validating expires_on exactly would require depending on internals of the credential and
    # patching time, so we'll be satisfied if expires_on is a datetime at least expires_in
    # seconds later than our call to get_token
    assert isinstance(expires_on, datetime.datetime)
    assert expires_on - now >= datetime.timedelta(seconds=expires_in)
def test_authenticate():
    client_id = "client-id"
    environment = "localhost"
    issuer = "https://" + environment
    tenant_id = "some-tenant"
    authority = issuer + "/" + tenant_id

    access_token = "***"
    scope = "scope"

    # mock AAD response with id token
    object_id = "object-id"
    home_tenant = "home-tenant-id"
    username = "******"
    id_token = build_id_token(aud=client_id,
                              iss=issuer,
                              object_id=object_id,
                              tenant_id=home_tenant,
                              username=username)
    auth_response = build_aad_response(uid=object_id,
                                       utid=home_tenant,
                                       access_token=access_token,
                                       refresh_token="**",
                                       id_token=id_token)

    transport = validating_transport(
        requests=[Request(url_substring=issuer)] * 4,
        responses=[get_discovery_response(authority)] * 2  # instance and tenant discovery
        + [
            mock_response(  # start device code flow
                json_payload={
                    "device_code": "_",
                    "user_code": "user-code",
                    "verification_uri": "verification-uri",
                    "expires_in": 42,
                }
            ),
            mock_response(json_payload=dict(auth_response, scope=scope)),  # poll for completion
        ],
    )

    credential = DeviceCodeCredential(
        client_id,
        prompt_callback=Mock(),  # prevent credential from printing to stdout
        transport=transport,
        authority=environment,
        tenant_id=tenant_id,
        _cache=TokenCache(),
    )
    record = credential.authenticate(scopes=(scope, ))

    # credential should have a cached access token for the scope used in authenticate
    token = credential.get_token(scope)
    assert token.token == access_token

    assert record.authority == environment
    assert record.home_account_id == object_id + "." + home_tenant
    assert record.tenant_id == home_tenant
    assert record.username == username
Exemplo n.º 7
0
def test_disable_automatic_authentication():
    """When configured for strict silent auth, the credential should raise when silent auth fails"""

    transport = Mock(send=Mock(side_effect=Exception("no request should be sent")))
    credential = DeviceCodeCredential("client-id", disable_automatic_authentication=True, transport=transport)

    with pytest.raises(AuthenticationRequiredError):
        credential.get_token("scope")
Exemplo n.º 8
0
def test_tenant_id_validation():
    """The credential should raise ValueError when given an invalid tenant_id"""

    valid_ids = {"c878a2ab-8ef4-413b-83a0-199afb84d7fb", "contoso.onmicrosoft.com", "organizations", "common"}
    for tenant in valid_ids:
        DeviceCodeCredential(tenant_id=tenant)

    invalid_ids = {"my tenant", "my_tenant", "/", "\\", '"my-tenant"', "'my-tenant'"}
    for tenant in invalid_ids:
        with pytest.raises(ValueError):
            DeviceCodeCredential(tenant_id=tenant)
def test_client_capabilities():
    """the credential should configure MSAL for capability CP1 (ability to handle claims challenges)"""

    transport = Mock(send=Mock(side_effect=Exception(
        "this test mocks MSAL, so no request should be sent")))
    credential = DeviceCodeCredential(transport=transport)

    with patch("msal.PublicClientApplication") as PublicClientApplication:
        credential._get_app()

    assert PublicClientApplication.call_count == 1
    _, kwargs = PublicClientApplication.call_args
    assert kwargs["client_capabilities"] == ["CP1"]
Exemplo n.º 10
0
def test_claims_challenge():
    """get_token and authenticate should pass any claims challenge to MSAL token acquisition APIs"""

    msal_acquire_token_result = dict(
        build_aad_response(access_token="**", id_token=build_id_token()),
        id_token_claims=id_token_claims("issuer", "subject", "audience", upn="upn"),
    )
    expected_claims = '{"access_token": {"essential": "true"}'

    transport = Mock(send=Mock(side_effect=Exception("this test mocks MSAL, so no request should be sent")))
    credential = DeviceCodeCredential(transport=transport)
    with patch.object(DeviceCodeCredential, "_get_app") as get_mock_app:
        msal_app = get_mock_app()
        msal_app.initiate_device_flow.return_value = {"message": "it worked"}
        msal_app.acquire_token_by_device_flow.return_value = msal_acquire_token_result

        credential.authenticate(scopes=["scope"], claims=expected_claims)

        assert msal_app.acquire_token_by_device_flow.call_count == 1
        args, kwargs = msal_app.acquire_token_by_device_flow.call_args
        assert kwargs["claims_challenge"] == expected_claims

        credential.get_token("scope", claims=expected_claims)

        assert msal_app.acquire_token_by_device_flow.call_count == 2
        args, kwargs = msal_app.acquire_token_by_device_flow.call_args
        assert kwargs["claims_challenge"] == expected_claims

        msal_app.get_accounts.return_value = [{"home_account_id": credential._auth_record.home_account_id}]
        msal_app.acquire_token_silent_with_error.return_value = msal_acquire_token_result
        credential.get_token("scope", claims=expected_claims)

        assert msal_app.acquire_token_silent_with_error.call_count == 1
        args, kwargs = msal_app.acquire_token_silent_with_error.call_args
        assert kwargs["claims_challenge"] == expected_claims
Exemplo n.º 11
0
    def __init__(self, synapse_dev_url: str, pool_name: str, datalake_dir: str,
                 executor_size: str, executors: int):
        tenant_id = '72f988bf-86f1-41af-91ab-2d7cd011db47'
        authority_host_uri = 'login.microsoftonline.com'
        client_id = '04b07795-8ddb-461a-bbee-02f9e1bf7b46'

        global login_credential_cache
        # use a global cache to store the credential, to avoid users from multiple login

        if login_credential_cache is None:
            # use DeviceCodeCredential if EnvironmentCredential is not available
            self.credential = ChainedTokenCredential(
                EnvironmentCredential(),
                DeviceCodeCredential(client_id,
                                     authority=authority_host_uri,
                                     tenant=tenant_id))
            login_credential_cache = self.credential
        else:
            self.credential = login_credential_cache

        self._api = SynapseJobRunner(synapse_dev_url,
                                     pool_name,
                                     executor_size=executor_size,
                                     executors=executors,
                                     credential=self.credential)
        self._datalake = DataLakeFiler(datalake_dir,
                                       credential=self.credential)
Exemplo n.º 12
0
def test_device_code_credential():
    expected_token = "access-token"
    user_code = "user-code"
    verification_uri = "verification-uri"
    expires_in = 42

    transport = validating_transport(
        requests=[Request()] *
        3,  # not validating requests because they're formed by MSAL
        responses=[
            # expected requests: discover tenant, start device code flow, poll for completion
            mock_response(
                json_payload={
                    "authorization_endpoint": "https://a/b",
                    "token_endpoint": "https://a/b"
                }),
            mock_response(
                json_payload={
                    "device_code": "_",
                    "user_code": user_code,
                    "verification_uri": verification_uri,
                    "expires_in": expires_in,
                }),
            mock_response(
                json_payload={
                    "access_token": expected_token,
                    "expires_in": expires_in,
                    "scope": "scope",
                    "token_type": "Bearer",
                    "refresh_token": "_",
                }),
        ],
    )

    callback = Mock()
    credential = DeviceCodeCredential(client_id="_",
                                      prompt_callback=callback,
                                      transport=transport,
                                      instance_discovery=False)

    token = credential.get_token("scope")
    assert token.token == expected_token

    # prompt_callback should have been called as documented
    assert callback.call_count == 1
    assert callback.call_args[0] == (verification_uri, user_code, expires_in)
Exemplo n.º 13
0
def test_device_code():
    import webbrowser

    def prompt(url, user_code, _):
        print("opening a browser to '{}', enter device code {}".format(url, user_code))
        webbrowser.open_new_tab(url)

    credential = DeviceCodeCredential(client_id=AZURE_CLI_CLIENT_ID, prompt_callback=prompt, timeout=40)
    get_token(credential)
Exemplo n.º 14
0
def test_client_capabilities():
    """the credential should configure MSAL for capability CP1 unless AZURE_IDENTITY_DISABLE_CP1 is set"""

    transport = Mock(send=Mock(side_effect=Exception("this test mocks MSAL, so no request should be sent")))

    with patch("msal.PublicClientApplication") as PublicClientApplication:
        DeviceCodeCredential(transport=transport)._get_app()

    assert PublicClientApplication.call_count == 1
    _, kwargs = PublicClientApplication.call_args
    assert kwargs["client_capabilities"] == ["CP1"]

    with patch.dict("os.environ", {"AZURE_IDENTITY_DISABLE_CP1": "true"}):
        with patch("msal.PublicClientApplication") as PublicClientApplication:
            DeviceCodeCredential(transport=transport)._get_app()

    assert PublicClientApplication.call_count == 1
    _, kwargs = PublicClientApplication.call_args
    assert kwargs["client_capabilities"] is None
Exemplo n.º 15
0
def test_tenant_id():
    client_id = "client-id"
    expected_token = "access-token"
    user_code = "user-code"
    verification_uri = "verification-uri"
    expires_in = 42

    transport = validating_transport(
        requests=[Request()] * 3,  # not validating requests because they're formed by MSAL
        responses=[
            # expected requests: discover tenant, start device code flow, poll for completion
            mock_response(json_payload={"authorization_endpoint": "https://a/b", "token_endpoint": "https://a/b"}),
            mock_response(
                json_payload={
                    "device_code": "_",
                    "user_code": user_code,
                    "verification_uri": verification_uri,
                    "expires_in": expires_in,
                }
            ),
            mock_response(
                json_payload=dict(
                    build_aad_response(
                        access_token=expected_token,
                        expires_in=expires_in,
                        refresh_token="_",
                        id_token=build_id_token(aud=client_id),
                    ),
                    scope="scope",
                ),
            ),
        ],
    )

    callback = Mock()
    credential = DeviceCodeCredential(
        client_id=client_id, prompt_callback=callback, transport=transport, instance_discovery=False,
    )

    now = datetime.datetime.utcnow()
    token = credential.get_token("scope", tenant_id="tenant_id")
    assert token.token == expected_token
Exemplo n.º 16
0
    def _initialize_credentials(self):
        if self.subscription_id is not None \
           and self.arm_base_url is not None:
            if self.vscode_tenant_id is None:
                self.vscode_tenant_id = self._get_tenant_id(
                    arm_base_url=self.arm_base_url,
                    subscription_id=self.subscription_id)
            if self.shared_cache_tenant_id is None:
                self.shared_cache_tenant_id = self._get_tenant_id(
                    arm_base_url=self.arm_base_url,
                    subscription_id=self.subscription_id)
            if self.interactive_browser_tenant_id is None:
                self.interactive_browser_tenant_id = self._get_tenant_id(
                    arm_base_url=self.arm_base_url,
                    subscription_id=self.subscription_id)

        credentials = []  # type: List[AsyncTokenCredential]
        if not self.exclude_token_file_credential:
            credentials.append(_TokenFileCredential())
        if not self.exclude_environment_credential:
            credentials.append(EnvironmentCredential(authority=self.authority))
        if not self.exclude_managed_identity_credential:
            credentials.append(
                ManagedIdentityCredential(
                    client_id=self.managed_identity_client_id))
        if not self.exclude_shared_token_cache_credential and SharedTokenCacheCredential.supported(
        ):
            try:
                # username and/or tenant_id are only required when the cache contains tokens for multiple identities
                shared_cache = SharedTokenCacheCredential(
                    username=self.shared_cache_username,
                    tenant_id=self.shared_cache_tenant_id,
                    authority=self.authority)
                credentials.append(shared_cache)
            except Exception as ex:  # pylint:disable=broad-except
                _LOGGER.info("Shared token cache is unavailable: '%s'", ex)
        if not self.exclude_visual_studio_code_credential:
            credentials.append(
                VisualStudioCodeCredential(tenant_id=self.vscode_tenant_id))
        if not self.exclude_cli_credential:
            credentials.append(AzureCliCredential())
        if not self.exclude_powershell_credential:
            credentials.append(AzurePowerShellCredential())
        if not self.exclude_interactive_browser_credential:
            credentials.append(
                InteractiveBrowserCredential(
                    tenant_id=self.interactive_browser_tenant_id))
        if not self.exclude_device_code_credential:
            credentials.append(
                DeviceCodeCredential(
                    tenant_id=self.interactive_browser_tenant_id))

        self.credentials = credentials
Exemplo n.º 17
0
    def _get_secret_client(self):
        if self.authn_type == "device":
            authority = self.authority_uri.replace("https://", "")
            credentials = DeviceCodeCredential(
                client_id=self.settings.CLIENT_ID,
                authority=authority,
                prompt_callback=_device_code_callback,
            )
        else:
            credentials = InteractiveBrowserCredential()

        # Create a secret client
        secret_client = SecretClient(self.vault_uri, credentials)
        return secret_client
Exemplo n.º 18
0
    def __init__(self, scheduler: HistoricNetworkScheduler):
        self.scheduler = scheduler
        self.subscribed_instruments = MutableSignal()
        self.scheduler.get_network().attach(self.subscribed_instruments)

        self.start_time = scheduler.get_clock().get_start_time()
        self.end_time = scheduler.get_clock().get_end_time()

        self.all_subscribed = set()
        self.book_signal_by_symbol = {}
        self.trade_signal_by_symbol = {}

        self.credential = DeviceCodeCredential(client_id=get_global_defaults()['azure']['client_id'],
                                               tenant_id=get_global_defaults()['azure']['tenant_id'])
Exemplo n.º 19
0
def _generate_credential(auth_method: str, token_path: Path, **kwargs):
    if auth_method == AuthMethod.DeviceCode.name:
        credential = DeviceCodeCredential(
            client_id=kwargs['client_id'],
            client_secret=kwargs['client_secret'],
            disable_automatic_authentication=True,
            tenant_id=kwargs['tenant_id'],
            **_get_cache_args(token_path))
    elif auth_method == AuthMethod.UsernamePassword.name:
        credential = UsernamePasswordCredential(
            client_id=kwargs['client_id'],
            client_credential=kwargs['client_secret'],
            disable_automatic_authentication=True,
            username=kwargs['username'],
            password=kwargs['password'],
            **_get_cache_args(token_path))
    elif auth_method == AuthMethod.ClientSecret.name:
        credential = ClientSecretCredential(
            client_id=kwargs['client_id'],
            tenant_id=kwargs['tenant_id'],
            client_secret=kwargs['client_secret'])
    else:
        raise RuntimeError(f'Auth method {auth_method} not found')
    return credential
Exemplo n.º 20
0
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# --------------------------------------------------------------------------------------------

from azure.identity import DeviceCodeCredential
from azure.mgmt.resource import SubscriptionClient
from azure.mgmt.resource import ResourceManagementClient

credential = DeviceCodeCredential()
subscription_client = SubscriptionClient(credential)

sub_list = subscription_client.subscriptions.list()
for sub in sub_list:
    print("Displaying resources in subscription ID:", sub.subscription_id)
    resource_client = ResourceManagementClient(credential, sub.subscription_id)
    res_list = resource_client.resources.list()
    for res in res_list:
        print()
        print("Resource:", res.id)
        print("\tLocation:", res.location)
        print("\tProperties:", res.properties)
Exemplo n.º 21
0
 def test_device_code(self):
     credential = DeviceCodeCredential(
         authority=self.cae_settings["authority"],
         tenant_id=self.cae_settings["tenant_id"])
     self.cae_test(credential)
Exemplo n.º 22
0
    def _get_creds_from_login(self, authentication, reason=None):

        # use normal Key Value
        from azure.keyvault.secrets import SecretClient

        if authentication == "auto":
            authentication = "browser" if pc_utils.has_gui() else "device-code"

        if authentication == "browser":
            console.print("authenticating with azure thru browser... ",
                          flush=True,
                          end="")
            from azure.identity import InteractiveBrowserCredential
            if self.azure_tenant_id is not None:
                credential = InteractiveBrowserCredential(
                    tenant_id=self.azure_tenant_id)
            else:
                credential = InteractiveBrowserCredential()
        elif authentication == "device-code":
            # console.print("authenticating with azure thru device code... ", flush=True, end="")
            from azure.identity import DeviceCodeCredential
            from azure.identity._constants import AZURE_CLI_CLIENT_ID

            console.print(
                "using device-code authorization (Azure AD currently requires 2-4 authenications here)"
            )
            if self.azure_tenant_id is not None:
                credential = DeviceCodeCredential(
                    tenant_id=self.azure_tenant_id,
                    client_id=AZURE_CLI_CLIENT_ID)
            else:
                credential = DeviceCodeCredential(
                    client_id=AZURE_CLI_CLIENT_ID)
        else:
            errors.syntax_error(
                "unrecognized authentication type '{}'".format(authentication))

        new_creds = True
        outer_token = credential.get_token()
        token = outer_token.token

        # expires = outer_token[1]
        # elapsed = expires - time.time()
        #print(" [new token expires in {:.2f} mins] ".format(elapsed/60), end="")

        # get keys from keyvault
        self.client = SecretClient(self.vault_url, credential=credential)
        key_text = self.get_secret_live("xt-keys")
        console.print("authenticated successfully", flush=True)

        #xt_client_cert = self.get_secret_live("xt-clientcert")
        xt_server_cert = self.get_secret_live("xt-servercert")

        # write all our creds to self.keys
        self.apply_creds(key_text)
        self.keys["xt_server_cert"] = xt_server_cert

        self.keys["object_id"] = self.get_me_graph_property(token, "id")

        # return creds as json string
        return json.dumps(self.keys)
Exemplo n.º 23
0
def test_no_scopes():
    """The credential should raise when get_token is called with no scopes"""

    credential = DeviceCodeCredential("client_id")
    with pytest.raises(ValueError):
        credential.get_token()
Exemplo n.º 24
0
from azure.identity import DeviceCodeCredential
from msgraphcore import GraphSession
import os, json

# Keep secrets/config in .env file
from dotenv import load_dotenv
load_dotenv()

# Graph API scopes we need
scopes = ['User.Read', 'User.ReadBasic.All']

# Use device code flow as we're a console app
# Set CLIENT_ID in .env file before running
browser_credential = DeviceCodeCredential(client_id=os.environ['CLIENT_ID'])
graph_session = GraphSession(browser_credential, scopes)

# User search term
searchString="Ben C"

# Call graph with a search for users
result = graph_session.get(f"/users?$filter=startswith(displayName, '{searchString}') or startswith(userPrincipalName, '{searchString}')")

# Just dump JSON to stdout, obviously a real app would do something less dumb
print(json.dumps(result.json(), indent=2))