AttributeError: 'DefaultAzureCredential' object has no attribute 'signed_session' - python

I'm using python sdk to query application insights using azure-applicationinsights==0.1.1.
Here is my code:
from azure.identity import DefaultAzureCredential
from azure.applicationinsights import ApplicationInsightsDataClient
from azure.applicationinsights.models import QueryBody
def query_app_insights():
query = 'myEvents | take 10'
application = 'my-app'
creds = DefaultAzureCredential()
client = ApplicationInsightsDataClient(creds)
result = client.query.execute(application, QueryBody(query=query))
I get this error:
AttributeError: 'DefaultAzureCredential' object has no attribute 'signed_session'
also tried:
creds = ClientSecretCredential(tenant_id='something',
client_id='something',
client_secret='something')
client = ApplicationInsightsDataClient(creds)
It gives me the same error.
also I tried:
from azure.identity import DefaultAzureCredential
from azure.applicationinsights import ApplicationInsightsDataClient
from azure.applicationinsights.models import QueryBody
from azure.common.credentials import ServicePrincipalCredentials
def query_app_insights():
query = 'myEvents | take 10'
application = 'my-app'
creds = ServicePrincipalCredentials(tenant='something',
client_id='something',
secret='something')
client = ApplicationInsightsDataClient(creds)
result = client.query.execute(application, QueryBody(query=query))
It complaints about my secret, but it is correct.
Any ideas?

AttributeError: 'DefaultAzureCredential' object has no attribute 'signed_session':
This error occurs frequently these days and I've also faced this couple of times. It actually means that "no signed session available for the given tenant".
After I've done a workaround, I found there is some issue addressed here with the SDK management libraries.
The DefaultAzureCredential class has been modified, and it no longer has the'signed session' attribute in few versions. To handle this, the most recent versions of the management libraries should be upgraded.
Need to check & resolve:
Installed the latest versions of the modules when you are importing in Python code.
azure-identity 1.12.0
azure-applicationinsights 0.1.1
Selected python 3.10 interpreter in visual studio code and ran the same code as yours in a virtual environment.
Created a virtual env and ran the project.
py -m venv env
.\env\Scripts\activate
Sometimes requirements.txt file will not get properly configured, In that scenario also you may face this error.
To avoid that, Freeze the requirements by using terminal:
pip freeze requirements.txt
After meeting all the above conditions, I tried in my environment and was able to proceed without any attribute errors.
Output:
Alternatively, I tried connecting with clientsecretcredential by registering to a new Application in AzureAD.
Note: Prefer to create a new registration instead of using old registrations as client_secrets might be expired.
TENANT_ID = '<TENANT_ID>'
CLIENT_ID = '<CLIENT_ID>'
CLIENT_SECRET = '<CLIENT_SECRET>'
SUBSCRIPTION_ID = '<SUBSCRIPTION_ID>'
from azure.identity import ClientSecretCredential
from azure.mgmt.keyvault import KeyVaultManagementClient
credentials = ClientSecretCredential(tenant_id=TENANT_ID, client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
credentialskeyvault = KeyVaultManagementClient(credentials, SUBSCRIPTION_ID)
print ("Logged")
Output:
To determine the precise status:
I simply deleted specific "rights/permissions" from my application in AzureAD and tested whether it threw an error when logged in.
Why because?
This error is usually thrown only after the user logged in. It states that the defaultazurecredential object was running without problem.
If the issue still persists, then you can wrap credentials by installing msrestazure module and create a credentialwrapperclass detailed by #lmazuel.

Related

Why does VSCode Python code completion not work for my firestore client variable?

I have the following python snippet...
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate("./cert.json")
firebase_admin.initialize_app(cred)
client = firestore.client()
client.
When I type the dot on the last line, no code completion options come up. On the 'firestore' variable, there are code completion options that come up.
I have the Python and Pylance extensions installed in VSCode. Is this a configuration issue, or is there something about what the client() method is returning, that it is not possible to infer its type?
Turns out there was already an open issue for this on the github repo, which also included a temporary (poor) workaround.
from firebase_admin import firestore
from google.cloud.firestore import Client as FirestoreClient # importing the return type of firestore.client()
db: FirestoreClient = firestore.client() # Adding an annotation to my db variable, to enable completion and syntax checking

Firestore SDK hangs in production

I'm using the Firebase Admin Python SDK to read/write data to Firestore. I've created a service account with the necessary permissions and saved the credentials .json file in the source code (I know this isn't the most secure, but I want to get the thing running before fixing security issues). When testing the integration locally, it works flawlessly. But after deploying to GCP, where our service is hosted, calls to Firestore don't work properly and retry for a while before throwing 503 Deadline Exceeded errors. However, SSHing into a GKE pod and calling the SDK manually works without issues. It's just when the SDK is used in code flow that causes problems.
Our service runs in Google Kubernetes Engine in one project (call it Project A), but the Firestore database is in another project (call it project B). The service account that I'm trying to use is owned by Project B, so it should still be able to access the database even when it is being initialized from inside Project A.
Here's how I'm initiating the SDK:
from firebase_admin import get_app
from firebase_admin import initialize_app
from firebase_admin.credentials import Certificate
from firebase_admin.firestore import client
from google.api_core.exceptions import AlreadyExists
credentials = Certificate("/path/to/credentials.json")
try:
app = initialize_app(credential=credentials, name="app_name")
except ValueError:
app = get_app(name="app_name")
client = client(app=app)
Another wrinkle is that another part of our code is able to successfully use the same service account to produce Firebase Access Tokens. The successful code is:
import firebase_admin
from firebase_admin import auth as firebase_admin_auth
if "app_name" in firebase_admin._apps:
# Already initialized
app = firebase_admin.get_app(name="app_name")
else:
# Initialize
credentials = firebase_admin.credentials.Certificate("/path/to/credentials.json")
app = firebase_admin.initialize_app(credential=credentials, name="app_name")
firebase_token = firebase_admin_auth.create_custom_token(
uid="id-of-user",
developer_claims={"admin": is_admin, "site_slugs": read_write_site_slugs},
app=app,
)
Any help appreciated.
Turns out that the problem here was a conflict between gunicorn's gevents and the SDK's use of gRCP. Something related to websockets. I found the solution here. I added the following code to our Django app's settings:
import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()

Exception: AttributeError: 'DefaultAzureCredential' object has no attribute 'signed_session' using Azure Function and Python

I wrote an Azure function that runs Python3 to simply turn on an Azure VM.
The function app has a system assigned managed identity that I've given VM contributor role. To have the function use the Managed Identity, I am using the DefaultAzureCredential() class.
The error I am getting is:
Exception: AttributeError: 'DefaultAzureCredential' object has no attribute 'signed_session'
I've done tons of research and can't seem to find the solution.
Here is the code that is related:
from azure.identity import DefaultAzureCredential
credentials = DefaultAzureCredential()
compute_client = ComputeManagementClient(credentials, subscription_id)
# Starting the VM
print('\nStarting VM ' + VM_NAME)
vm_start = compute_client.virtual_machines.start(
RG_NAME, VM_NAME)
vm_start.wait()
You'll have to forgive me, I'm only new to Python, but very interested in learning.
EDIT May 2022:
As of May 2022, all SDKs have been re-released with native support for azure-identity. If you still encounter this error with a given SDK on its latest version, please open an issue asking for a re-release of that SDK here: https://github.com/Azure/azure-sdk-for-python/issues
Original response:
This is addressed here: https://learn.microsoft.com/en-us/azure/developer/python/azure-sdk-authenticate?tabs=cmd
Search "Using DefaultAzureCredential with SDK management libraries" on this page and it will take you to the section that covers your problem in more detail.
In a nutshell....
They updated the DefaultAzureCredential class and it no longer has a 'signed_session' attribute. The newest versions of the management libraries should be updated to handle this. As mentioned in another solution, update your azure-cli library to ensure you have the latest. However, not all of the management libraries have been updated yet. You can use this wrapper created by a member of the Azure SDK engineering team for the time being.
https://gist.github.com/lmazuel/cc683d82ea1d7b40208de7c9fc8de59d
# Wrap credentials from azure-identity to be compatible with SDK that needs msrestazure or azure.common.credentials
# Need msrest >= 0.6.0
# See also https://pypi.org/project/azure-identity/
from msrest.authentication import BasicTokenAuthentication
from azure.core.pipeline.policies import BearerTokenCredentialPolicy
from azure.core.pipeline import PipelineRequest, PipelineContext
from azure.core.pipeline.transport import HttpRequest
from azure.identity import DefaultAzureCredential
class CredentialWrapper(BasicTokenAuthentication):
def __init__(self, credential=None, resource_id="https://management.azure.com/.default", **kwargs):
"""Wrap any azure-identity credential to work with SDK that needs azure.common.credentials/msrestazure.
Default resource is ARM (syntax of endpoint v2)
:param credential: Any azure-identity credential (DefaultAzureCredential by default)
:param str resource_id: The scope to use to get the token (default ARM)
"""
super(CredentialWrapper, self).__init__(None)
if credential is None:
credential = DefaultAzureCredential()
self._policy = BearerTokenCredentialPolicy(credential, resource_id, **kwargs)
def _make_request(self):
return PipelineRequest(
HttpRequest(
"CredentialWrapper",
"https://fakeurl"
),
PipelineContext(None)
)
def set_token(self):
"""Ask the azure-core BearerTokenCredentialPolicy policy to get a token.
Using the policy gives us for free the caching system of azure-core.
We could make this code simpler by using private method, but by definition
I can't assure they will be there forever, so mocking a fake call to the policy
to extract the token, using 100% public API."""
request = self._make_request()
self._policy.on_request(request)
# Read Authorization, and get the second part after Bearer
token = request.http_request.headers["Authorization"].split(" ", 1)[1]
self.token = {"access_token": token}
def signed_session(self, session=None):
self.set_token()
return super(CredentialWrapper, self).signed_session(session)
if __name__ == "__main__":
import os
credentials = CredentialWrapper()
subscription_id = os.environ.get("AZURE_SUBSCRIPTION_ID", "<subscription_id>")
from azure.mgmt.resource import ResourceManagementClient
client = ResourceManagementClient(credentials, subscription_id)
for rg in client.resource_groups.list():
print(rg.name)
Your code would then look like:
from cred_wrapper import CredentialWrapper
credentials = CredentialWrapper()
compute_client = ComputeManagementClient(credentials, subscription_id)
# Starting the VM
print('\nStarting VM ' + VM_NAME)
vm_start = compute_client.virtual_machines.start(
RG_NAME, VM_NAME)
vm_start.wait()
You should be cooking from there!
Looks like it's fixed if you use the preview version of azure-mgmt-compute (17.0.0b1)
Another gotchya because of the version bump is they changed the start function from start to begin_start.
Hope this helps somebody!
I ran into this issue and cannot upgrade the Azure management libraries in question. However, the wrapper does not work as it leads to another error:
self._token = self._credential.get_token(*self._scopes)
AttributeError: 'CredentialWrapper' object has no attribute 'get_token'
To get around this I had to pass through the get_token call in the CredentialWrapper class:
class CredentialWrapper(BasicTokenAuthentication):
def __init__(...):
...
# Set credential to instance variable
self.credential = credential
...
def get_token(self, *scopes, **kwargs):
# Pass get_token call to credential
return self.credential.get_token(*scopes, **kwargs)
For reference the library versions I'm using are:
azure-common==1.1.25
azure-core==1.9.0
azure-identity==1.5.0
azure-mgmt-compute==17.0.0
azure-mgmt-core==1.2.2
azure-mgmt-network==16.0.0
azure-mgmt-resource==10.2.0
msrestazure==0.6.4
I have faced the similar (Signed_Session) kind of issue while working with Azure nsgs and have fixed it. There might be 2 causes.
Azure library versions mismatch.
for me combination of below 2 libraries are working.
azure-identity==1.6.1 and azure-mgmt-network==19.0.0
May be you are importing the incorrect library.
I am working with nsgs for this. I installed the library called "azure-mgmt" and imported the "NetworkManagementClient" class then I have faced "signed session" issue. Later, I uninstalled the "azure-mgmt" library and installed another library, "azure-mgmt-network==19.0.0" and now it is working fine.
To import/work with "azure.mgmt.network import NetworkManagementClient", we need to install "azure-mgmt-network==19.0.0" library but not "azure-mgmt.
Just think on above 2 ways..it may helps you.

Azure Python SDK - code only fails when debugging in VS Code

VS Code 1.14.0, Python 3.8.0 (in venv).
When I run the following code in VS Code, it works. When I run it in the debugger even with no breakpoints, it fails. This might be something to do with venvs, but I don't know. Ideas? BTW - I am referencing the other packages for what I will be building.
From the Bash shell, I have the following environment variables:
export AZURE_TENANT_ID = "tenant ID"
export AZURE_CLIENT_ID = "client ID"
export AZURE_CLIENT_SECRET = "client secret"
export AZURE_SUBSCRIPTION_ID = "subscription ID"
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.keyvault.keys import KeyClient
from azure.mgmt.keyvault import KeyVaultManagementClient
from azure.core.exceptions import HttpResponseError
import datetime
import os
credential = DefaultAzureCredential()
secret_client = SecretClient(vault_url="https://blahblahblah.vault.azure.net/", credential=credential)
print(os.environ["AZURE_TENANT_ID"])
print(os.environ["AZURE_CLIENT_ID"])
print(os.environ["AZURE_CLIENT_SECRET"])
print(os.environ["AZURE_SUBSCRIPTION_ID"])
try:
print("\n.. Get a Secret by name")
secret = secret_client.get_secret("mySecret")
print("Secret with name '{0}' was found with value '{1}'.".format(secret.name, secret.value))
except HttpResponseError as e:
print("\nThis sample has caught an error. {0}".format(e.message))
When I run this in DEBUG in VS Code, this is the error:
This sample has caught an error.
No credential in this chain provided a token.
Attempted credentials:
EnvironmentCredential: Incomplete environment configuration
ImdsCredential: IMDS endpoint unavailable
SharedTokenCacheCredential: The shared cache contains no signed-in accounts. To authenticate with SharedTokenCacheCredential, login
through developer tooling supporting Azure single sign on
What I have learned is the printed OS environ variables are accurate when I Run Python File in Terminal, but when I run the file in debug, it errors printing the first OS environ variable saying it doesn't exist.
This is my ignorance on setting debug correctly. Any pointers will help (and thank you for your responses)!**
To make the answer visible to others, I'm summarizing the answer shared in comment:
This issue occurred because of the missing of environment variables under debugger mode. Add the environment variables to the launch.json file solved this issue.
From my experience, BASH does not like spaces, when declaring variables;
export AZURE_TENANT_ID="tenant ID"
export AZURE_CLIENT_ID="client ID"
export AZURE_CLIENT_SECRET="client secret"
export AZURE_SUBSCRIPTION_ID="subscription ID"
Might do the trick.

How do I connect to a kerberos authenticated REST service in Python on Windows

I am trying to create a very simple Python script to download the contents of an internal service at my company that sits within our firewall and authenticates using kerberos.
When I installed the requests_kerberos module I first edited the import kerberos in it to use import kerberos_sspi as kerberos instead after having installed the kerberos_sspi module.
Thus I have the following Python script
import requests
from requests_kerberos import HTTPKerberosAuth
response = requests.get('http://service.internaldomain',auth=HTTPKerberosAuth())
print response
While trying to process the 401 it crashes out with the error.
error: (-2146893053, 'InitializeSecurityContext', 'The specified target is unknown or unreachable')
While looking into seeing if I could do this with curl instead I ran kinit and noticed that it asked me for the password to authorisation with the following prompt:
Password for username#additionalInternalDomain.internaldomain
Thus I wondered if this might be what is causing the issue.
I have tried multiple libraries on python and failed when trying to authenticate from a windows machine.There is no easy way. The Kerberos libraries mainly work on Linux. The workarounds for Windows do not work. So what can be the solution to this.
Well... be a Roman while in Rome. Try the windows native libraries from Python.
import sys
import clr
from System.Net.Http import *
myClienthandler = HttpClientHandler()
myClienthandler.UseDefaultCredentials = True
myClient = HttpClient(myClienthandler)
x = myClient.GetStringAsync("putyourURLwithinthequoteshere")
myresult = x.Result
print(myresult)
Note that the this python script will have to run by the user who has access to the URL you are trying to access. By setting UseDefaultCredentials property as True, you are passing the Kerberos tickets for the logged in user.
The server is giving you a 401 challenge - and the client (usually a browser or even curl) provides the credentials in a subsequent call. If you are already logged in at your domain - try forcing a pre-emptive hop, i.e. you’d carry your Kerberos ticket with your call and the server will not give you a 401 challenge:
kerberos_auth = HTTPKerberosAuth(force_preemptive=True)
r = requests.get("http://myhost/DXAPIGraphQL/api/graphql", auth=kerberos_auth)
If the above doesn't help look into the:
principal and hostname_override arguments of the HTTPKerberosAuth class.
I had to connecto to a REST API who's in a keberized environment just now.
After some reading, i came to this (and it worked):
tk = 'long_kerberos_token'
headers = {'Authorization': 'Negotiate' + tk}
r = requests.get(url=PING_URL, headers=headers)

Categories

Resources