I am trying to migrate my simple python script that accesses an O365 email account using basic auth to modern auth:
Here's the current setup.
import exchangelib as exch
credentials = exch.Credentials('my_username', 'my_password')
configInfo = exch.Configuration(server='smtp.office365.com', credentials=credentials)
tz = exch.EWSTimeZone.localzone()
account = exch.Account(primary_smtp_address='my_email_address', config=configInfo, autodiscover=False, access_type=exch.DELEGATE)
It works fine. From here I can access items such as account.inbox to iterate emails, etc.
Moving to Azure Identity, my devops team assigned me the following:
a registered app in the Azure Portal
an app ID
an object ID
a tenant ID
a secret value ID
a secret key ID
an https://ps.outlook.com/ URL
I've run this...
pip install azure-identity
And now I can run this...
from azure.identity import DefaultAzureCredential
# Now what? A service client perhaps?
I'm at a loss as to what comes next. My goal is to authenticate using the IDs above, then create an account object as before, and continue processing. Can anyone help? Thank you.
Related
My Sql server DB password is saved on Azure app vault which has DATAREF ID as a identifier. I need that password to create spark dataframe from table which is present in SQL server. I am running this .py file on google Dataproc cluster. How can I get that password using python?
Since you are accessing an Azure service from a non-Azure service, you will need a service principal. You can use certificate or secret. See THIS link for the different methods. You will need to give the service principal proper access and this will depend if you are using RBAC or access policy for your key vault.
So the steps you need to follow are:
Create a key vault and create a secret.
Create a Service principal or application registration. Store the clientid, clientsecret and tenantid.
Give the service principal proper access to the key vault(if you are using access policies) or to the specific secret(if you are using RBAC model)
The python link for the code is HERE.
The code that will work for you is below:
from azure.identity import ClientSecretCredential
from azure.keyvault.secrets import SecretClient
tenantid = <your_tenant_id>
clientsecret = <your_client_secret>
clientid = <your_client_id>
my_credentials = ClientSecretCredential(tenant_id=tenantid, client_id=clientid, client_secret=clientsecret)
secret_client = SecretClient(vault_url="https://<your_keyvault_name>.vault.azure.net/", credential=my_credentials)
secret = secret_client.get_secret("<your_secret_name>")
print(secret.name)
print(secret.value)
I'm trying to get access to my outlook calandar using the following code:
from bs4 import BeautifulSoup
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from O365 import Account
from O365 import Connection
from O365 import FileSystemTokenBackend
from configparser import ConfigParser
file='config.py'
config = ConfigParser()
config.read(file)
def authenticate_outlook():
# authenticate microsoft graph api credentials
credentials = (config['account']['outlook_client_id'], config['account']['outlook_client_id'])
token_backend = FileSystemTokenBackend(
token_path=config['account']['outlook_token_path'], token_filename=config['account']['outlook_token_filename']
)
account = Account(credentials, token_backend=token_backend)
if not account.is_authenticated:
# not authenticated, throw error
account.authenticate(scopes=config['account']['outlook_scopes'])
connection = Connection(credentials, token_backend=token_backend, scopes=config['account']['outlook_scopes'])
connection.refresh_token()
print("Authenticated Outlook.")
return account
# authenticate outlook credentials
outlook_acct = authenticate_outlook()
And i'm using this config.py file:
[account]
outlook_client_id = "86ae4814-fad2-4cc0-b76e-57bd4b20476c"
outlook_client_secret = "06ecc895-b04d-4578-9c3c-b5a8ccc026ab"
outlook_scopes = ["basic", "calendar"]
outlook_token_path = "./credentials/"
outlook_token_filename = "outlook_token.txt"
previous_days = 40 # retrieve this many past days of events
future_days = 365 # retrieve this many future days of events
Then I get this error:
AADSTS700016: Application with identifier '"86ae4814-fad2-4cc0-b76e-57bd4b20476c"' was not found in the directory 'z7fs3'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
I checked that i'm using the good app ID and the secret ID, They match with my app on AZURE, I don't ound the issue yet.
Thank you.
The issue indicates that there is a mismatch between the tenant where your app is registered and where you have stated that your app is registered in either the application code or the portal.
You must set the tenant ID in your codE for the application. This is usually found in the web.config or app settings files.
Then, using the same tenant ID that you specified in your code, you must register the application on the portal. Make sure your application ID and client ID are the same on both sides, and that all of the values in your app settings/web.config are the same as what you have in the portal.
Also, using the ID in the Client secret section instead of the Application (client) ID is a common cause of this problem.
Today I'm trying to do read calendar from outlook. I created a new app through Microsoft Azure then setted a secret key and added a api permissions. When I was trying to authenticate via simple script I caught an error
The request is not valid for the application's 'userAudience' configuration.
In order to use /common/ endpoint%2c the application must not be configured with 'Consumer' as the user audience.
The userAudience should be configured with 'All' to use /common/ endpoint
This is my script
from O365 import Account, MSGraphProtocol
CLIENT_ID = 'MY CLIENT ID'
SECRET_ID = 'MY SECRET ID'
credentials = (CLIENT_ID, SECRET_ID)
protocol = MSGraphProtocol()
scopes = ['Calendars.Read.Shared']
account = Account(credentials, protocol=protocol)
if account.authenticate(scopes=scopes):
print('Authenticated!')
Could you tell me a reason of this error and how should i fix it?
It looks like you trying to use the client_credentials flow but your firstly using a Delegate permission which isn't correct. So in your Application registration you need to make sure you have assigned the Application permission for Calendars eg
to use the Client_credentials flow you need to first find your tenantId (if you don't already know it) you can do this in python eg using requests (you need to replace yourdomain.com with the domain your using
requests.get('https://login.windows.net/yourdomain.com/v2.0/.well-known/openid-configuration').json()["token_endpoint"]
Then take the guid part of the response eg
'https://login.windows.net/1c3a18bf-da31-4f6c-xxxx-2c06c9cf5ae4/oauth2/v2.0/token'
Then your code should look like where
from O365 import Account
credentials = ('my_client_id', 'my_client_secret')
# the default protocol will be Microsoft Graph
account = Account(credentials, auth_flow_type='credentials', tenant_id='1c3a18bf-da31-4f6c-xxxx-2c06c9cf5ae4')
if account.authenticate():
print('Authenticated!')
I want to list azure security center alerts using the python SDK.
I found this package:
https://pypi.org/project/azure-mgmt-security/
It must be included in the microsoft documentation:
https://learn.microsoft.com/en-gb/python/azure/?view=azure-python
https://github.com/Azure/azure-sdk-for-python
but I can not find any reference or example.
Does anyone know where I can find this information?
Best regards.
I can just give a rough reference.
After install the package azure-mgmt-security, you should use List method in the package, source code is here.
Here is the the doc on how to authentication.
Here is doc on how to get tenantId / client_id / key.
Here is my code:
from azure.mgmt.security import SecurityCenter
from azure.common.credentials import ServicePrincipalCredentials
subscription_id = "xxxx"
# Tenant ID for your Azure subscription
TENANT_ID = '<Your tenant ID>'
# Your service principal App ID
CLIENT = '<Your service principal ID>'
# Your service principal password
KEY = '<Your service principal password>'
credentials = ServicePrincipalCredentials(
client_id = CLIENT,
secret = KEY,
tenant = TENANT_ID
)
client = SecurityCenter(credentials=credentials,subscription_id=subscription_id,asc_location="centralus")
client.alerts.list()
Also, you can use List Alerts api with a http request in python.
As of today, February 2021, Microsoft again changed the way credentials are instantiated. Here is the current one:
from azure.identity import DefaultAzureCredential
# Acquire a credential object for the app identity. When running in the cloud,
# DefaultAzureCredential uses the app's managed identity (MSI) or user-assigned service principal.
# When run locally, DefaultAzureCredential relies on environment variables named
# AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID.
credential = DefaultAzureCredential()
And it also changed the SecurityCenter signature, the credentials parameter was renamed to credential without the "s".
Full documentation here.
I'm trying to submit documents to an Elasticsearch index from a Python Lambda script running as a role which has the AmazonESFullAccess policy attached. I am creating the requests with the python elasticsearch library, and signing them with the aws_requests_auth library.
cred = boto3.session.Session().get_credentials()
es_host = '<elasticsearch-server>'
auth = AWSRequestsAuth(
aws_access_key=cred.access_key,
aws_secret_access_key=cred.secret_key,
aws_host=es_host,
aws_region='us-east-1',
aws_service='es')
ES_CLIENT = Elasticsearch(
host=es_host,
port=80,
connection_class=RequestsHttpConnection,
http_auth=auth)
Then sending bulk create requests as follows:
ES_CLIENT.bulk(
index='test_index',
body=docs)
This is failing with the following:
TransportError(403, u'{"message": "The security token included in the
request is invalid." }'): AuthorizationException ...
Though the same code works when running with admin user access keys.
Why do these requests fail when running as a role with 'full ES access'?
Because Elasticsearch is a seperate entity to AWS, but a version is hosted by AWS it seems that elasticsearch doesn't treat IAM the same way you'd expect.. AWS has something in place that tries, but doesn't quite work with just an access_key and secret_key. It needs the session Token as well.
The answer to this is to use the cred.token along with the access key and secret key and then pass it into your AWSRequestsAuth object:
auth = AWSRequestsAuth(
aws_access_key=cred.access_key,
aws_secret_access_key=cred.secret_key,
aws_token=cred.token,
aws_host=es_host,
aws_region='us-east-1',
aws_service='es')