I am new to Azure. I need to set up an automation script to list all Ips in azure using Azure Rest APi in Python. However i couldnt been able to get any result from the API url I am passing to the request.
I am following this https://learn.microsoft.com/en-us/rest/api/virtualnetwork/public-ip-addresses/list-all#code-try-0
In code block, I have tried using requests
import requests
apijson = requests.get("https://management.azure.com/subscriptions/9540b342-9f94-4dd9-9eca-0698dda0107c/providers/Microsoft.Network/publicIPAddresses?api-version=2021-05-01"
I know I need to setup Oauth/authentication but I don't know what I need to declare or pass any token from my script
I know I need to setup Oauth/authentication but I don't know what I need to declare or pass any token from my script
You can declare/pass token, for example:
import sys
import requests
import json
import time
test_api_url = "Add URL which you want to test"
#function to obtain a new OAuth 2.0 token from the authentication server
def get_new_token():
auth_server_url = "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token'"
client_id = 'XXXX-XXXX-XXXX'
client_secret = 'XXXX'
token_req_payload = {'grant_type': 'client_credentials'}
token_response = requests.post(auth_server_url,
data=token_req_payload, verify=False, allow_redirects=False,
auth=(client_id, client_secret))
if token_response.status_code !=200:
print("Failed to obtain token from the OAuth 2.0 server", file=sys.stderr)
sys.exit(1)
print("Successfuly obtained a new token")
tokens = json.loads(token_response.text)
return tokens['access_token']
token = get_new_token()
while True:
api_call_headers = {'Authorization': 'Bearer ' + token}
api_call_response = requests.get(test_api_url, headers=api_call_headers,
verify+False)
if api_call_response.status_code == 401:
token = get_new_token()
else:
print(api_call_response.text)
time.sleep(30)
You can refer to How to authenticate and authorize Python applications on Azure, Azure AD Authentication Python Web API and Protect an API by using OAuth 2.0 with Azure Active Directory and API Management
Related
I am having trouble sending an authenticated firestore REST API request from a cloud function. The request needs to have an oauth2 token in the header. I've followed the docs here https://cloud.google.com/functions/docs/securing/authenticating and tried the python function they provided, but that still does not give the right authentication. What has worked so far is copying the token from gcloud auth application-default print-access-token but that expires after an hour. Any ideas?
import urllib
import google.auth.transport.requests
import google.oauth2.id_token
def make_authorized_get_request(endpoint, audience):
"""
make_authorized_get_request makes a GET request to the specified HTTP endpoint
by authenticating with the ID token obtained from the google-auth client library
using the specified audience value.
"""
# Cloud Functions uses your function's URL as the `audience` value
# audience = https://project-region-projectid.cloudfunctions.net/myFunction
# For Cloud Functions, `endpoint` and `audience` should be equal
req = urllib.request.Request(endpoint)
auth_req = google.auth.transport.requests.Request()
id_token = google.oauth2.id_token.fetch_id_token(auth_req, audience)
req.add_header("Authorization", f"Bearer {id_token}")
response = urllib.request.urlopen(req)
return response.read()
The above function results in aurllib.error.HTTPError: HTTP Error 401: Unauthorized"
The solution in my case was to add datastore.importExportAdmin "Cloud Datastore Import Export Admin" role to the service account that would generate the token. And to use the code below to generate a token from credentials:
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
request = google.auth.transport.requests.Request()
credentials.refresh(request)
https://cloud.google.com/firestore/docs/security/iam#roles
I am trying to convert the following command from CLI (that works) to python but I am having some problems.
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL
The problem is that I cannot request a valid Bearer with application default local credentials token to make authorized request to Google Cloud Run. If I generate Bearer token from CLI gcloud auth print-identity-token and use it in a python request all works fine
request_url = 'https://<my endpoint>'
identity_token = '<>' # response of gcloud auth print-identity-token)
header= {'Authorization': f'Bearer {identity_token}'}
requests.get(url=request_url, headers=receiving_service_headers)
From google auth documentation I understood that Cloud Run communicationis based on Identity Tokens that support Impersonated authentication but I cannot generate valid credential.
from google.auth import impersonated_credentials, default
from google.auth.transport.requests import AuthorizedSession
request_url = 'https://<my endpoint>'
source_credentials, project = default()
creds = impersonated_credentials.IDTokenCredentials(
source_credentials,
target_audience=request_url)
authed_session = AuthorizedSession(creds)
resp = authed_session.get(request_url)
print(resp)
bui I get following error
google.auth.exceptions.GoogleAuthError: Provided Credential must be impersonated_credentials
Thanks
Today it's impossible. I talked about it in an article. You need a service account to generate a valid JWT token with the Google Auth library. It's the same problem with all the library and all the languages.
Last week, I pushed a merge request in the Java auth library to solve this. I don't know why Google don't implement it by itself.
On your local environment, if you want to use the same code locally and in the cloud, you have to generate a service account key file and use it with ADC. And it's sadly a security issue...
Please follow the enter link if you want to convert the curl command to python request. Here is converted code:
import requests
headers = {
'Authorization': 'Bearer $(gcloud auth print-identity-token)',
}
response = requests.get('http://SERVICE_URL', headers=headers)
I'm using cloud functions with python as the serverless to my project
I by triggering the Cloud Function to add a user to my BigQuery project so he can have access to some tables.
I need to get access token from gsutil in order to use the API to give user access permissions.
How can I give IAM role or get access token to my project so I can use it from my Cloud Function to give users (by email) access to my BigQuery.
I'm using those API endpoints:
ENDPOING_GETIAMPOLICY = 'https://cloudresourcemanager.googleapis.com/v1/projects/{resource}:getIamPolicy'
ENDPOING_SETIAMPOLICY = 'https://cloudresourcemanager.googleapis.com/v1/projects/{resource}:setIamPolicy'
In order to use this ENDPOING_GETIAMPOLICY endpoint, I need ACCESS_TOKEN
# Preparing get all the current iam users
params = {
'access_token': ACCESS_TOKEN
}
resp = requests.post(ENDPOING_GETIAMPOLICY.format(resource=resource), params=params)
I'm open to other suggestions for how to do it.
In order to get the token using Python, you can do something similar to this:
Add this to requirements.txt:
oauth2client>=4.1.2
Retrieve the token in the Cloud Function like this:
def getAccessToken():
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
credentials.get_access_token()
token = credentials.access_token
return verifyToken(token)
def verifyToken(token):
import requests
response = requests.get('https://www.googleapis.com/bigquery/v2/projects/[PROJECT_ID]/datasets', headers={'Authorization': 'Bearer ' + token})
return (response.content)
This will return you the Access Token in String format, you can then add it to the JSON if that is what you need.
I have a Python app running on Google App Engine. I am trying to perform an Oauth 2 authentication without using oauth libraries.
I need a session to store the information returned from the Google auth code (access token) and send it to the next request. When I try to store the JSON into a flask session key, my app goes to an Internal Server Error with no debug info. My code is practically a copy-paste from Google's HTTP Rest example in their Oauth2 for web server apps documentation (link commented in code).
import logging
import flask
from flask import render_template, session
import json
import urllib
from google.appengine.api import urlfetch
#Code from https://developers.google.com/identity/protocols/OAuth2WebServer
app = flask.Flask(__name__)
CLIENT_ID = '[].apps.googleusercontent.com'
CLIENT_SECRET = '[]'
SCOPE = 'email'
REDIRECT_URI = 'https://[].appspot.com/oauthcallback'
#check for last oauth step, if not go to intermediate steps
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.render_template('index.html')
credentials = json.loads(flask.session['credentials'])
if credentials['expires_in'] <= 0:
return flask.redirect(flask.url_for('oauthcallback'))
else:
headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
req_uri = 'https://www.googleapis.com/oauth2/v2/userinfo'
r = requests.get(req_uri, headers=headers)
return r.text
#ask user to sign in, send code to googleapi to get token
#app.route('/oauthcallback')
def oauthcallback():
if 'code' not in flask.request.args:
auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'}
r = urlfetch.fetch("https://www.googleapis.com/oauth2/v4/token", payload=data, method="POST")
#return r.content #prints json
flask.session['credentials'] = r.content #breaks here
return flask.redirect(flask.url_for('index'))
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = True
app.run()
Did you enable the redirect URI?
https://developers.google.com/api-client-library/python/auth/web-app
Create authorization credentials
Any application that uses OAuth 2.0 to access Google APIs must have authorization credentials that identify the application to Google's OAuth 2.0 server. The following steps explain how to create credentials for your project. Your applications can then use the credentials to access APIs that you have enabled for that project.
Open the Credentials page in the API Console.
Click Create credentials > OAuth client ID.
Complete the form. Set the application type to Web application. Applications that use languages and frameworks like PHP, Java, Python, Ruby, and .NET must specify authorized redirect URIs. The redirect URIs are the endpoints to which the OAuth 2.0 server can send responses.
For testing, you can specify URIs that refer to the local machine, such as http://localhost:8080. With that in mind, please note that all of the examples in this document use http://localhost:8080 as the redirect URI.
I am very interested in using the new service recently released for secret management within Azure. I have found a few example guides walking through how to interact with key vault via powershell cmdlets and c#, however haven't found much at all in regards to getting started with using the rest API.
The thing I am particularly confused with is the handling of oauth2 w/ active directory. I have written a oauth2 application listener, built a web application with an AD instance and can now generate a "access_token". It is very unclear to me how to proceed beyond this though, as I seem to consistently receive a 401 HTTP resp code whenever attempting to use my access_token to perform a key vault API call.
Any guides / tips on using azure key vault with python would be greatly appreciated!
Here are some steps you'll need to do before the following code will work... Hopefully I remembered everything!
You'll need to have an application in AD with at least get access
note: you need this to get the CLIENT_ID and CLIENT_SECRET anyway
then run:
azure keyvault set-policy --vault-name 'VAULTNAME' --spn CLIENT_ID --perms-to-secrets '["get"]'
You'll also need the id's for your secrets, which you can get with the Azure CLI using:
azure keyvault secret show [vault] [secret]
or
azure keyvault secret show -h # if this is unclear
Copy the key (last argument in the URL)
Then the following code will allow you to query the key vault using oauth2:
import json
import requests
AUTHORITY_HOST = "login.windows.net"
TENANT_ID = < your tenant id >
CLIENT_ID = < your client id >
CLIENT_SECRET = < your client secret >
VAULT = 'MyVault'
data = { "grant_type" : "client_credentials",
"client_id" : CLIENT_ID,
"client_secret" : CLIENT_SECRET,
"resource" : "https://vault.azure.net"
}
secrets = [( "i_like_pie", "8a7680a2cf5e4d539494aa0ce265297" )]
headers = { "Content-Type" : "application/x-www-form-urlencoded" }
r = requests.post("https://login.windows.net/{}/oauth2/token".format(TENANT_ID), data=data, headers=headers)
access_token = r.json()['access_token']
for secret, secret_id in secrets.iteritems():
headers = {"Authorization":"Bearer {}".format(access_token) }
r = requests.get('https://{}.vault.azure.net/secrets/{}/{}?api-version=2015-06-01'.format(VAULT, secret, secret_id), headers=headers)
print('##### {} #####'.format(secret))
print(r.json())
print('')
Here are a couple of things that you can check:
When you make the request for the Bearer token, make sure that you include the "resource" header, and that it is set to "https://vault.azure.net". If you don't, you'll get a token, but you won't be able to access any vault data with it.
When you make a call to the vault.azure.net URL, make sure you include the correct "api-version" It can be found in the API documentation. The current value is "2015-02-01-preview".
Of course, check that the Key Vault Access Policy is set correctly for the vault you are trying to access.
For working with Key Vault's REST API, there's reference documentation and service documentation that should help.
Using Key Vault with Python is now more easily done with the Azure SDK. There are three Python packages for working with existing vault data, and one for creating/managing vaults:
azure-keyvault-certificates (Migration guide)
azure-keyvault-keys (Migration guide)
azure-keyvault-secrets (Migration guide)
azure-mgmt-keyvault
azure-identity is also the package that should be used with these for authentication.
With the SDK, using an access token to work with an existing vault from an authorized application is as easy as creating a credential and client:
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
credential = DefaultAzureCredential()
client = SecretClient("https://{vault-name}.vault.azure.net", credential)
secret = client.get_secret("secret-name")
(I work on the Azure SDK in Python)
When Key Vault returns a 401 response, it includes a www-authenticate header containing authority and resource. You must use both to get a valid bearer token. Then you can redo your request with that token, and if you use the same token on subsequent requests against the same vault, it shouldn't return a 401 until the token expires.
You can know the authority and resource in advance, but it's generally more robust to prepare your code to always handle the 401, specially if you use multiple vaults.
Be sure to only trust on a www-authenticate header of a valid SSL connection, otherwise you might be a victim of spoofing!
I have written a simple python wrapper for the REST APIs for Azure Key Vault.
You can check out out here
AzureKeyVaultPythonSDK
Crust of the logic is here
class AzureKeyVaultManager(object):
section_name="KeyVaultSection"
# Constructor
def __init__(self, fileName="private.properties"):
prop_file=os.path.dirname(os.path.realpath(sys.argv[0])) + "/" + fileName
config = ConfigParser.RawConfigParser()
config.read(prop_file)
self.client_id=config.get(self.section_name,'client.id')
self.client_secret=config.get(self.section_name,'client.secret')
self.tenant_id=config.get(self.section_name,'tenant.id')
self.resource=config.get(self.section_name,'resource')
self.key_vault=config.get(self.section_name,'key.vault')
# Authenticate
def initialize(self):
if self.client_id and self.client_secret and self.tenant_id and self.resource and self.key_vault:
print "Got all the properties from file "
token_url="https://login.windows.net/{0}/oauth2/token".format(self.tenant_id)
payload = {'client_id':self.client_id, 'client_secret':self.client_secret, 'resource':self.resource, 'grant_type':'client_credentials'}
response=requests.post(token_url, data=payload).json()
self.access_token=response['access_token']
else:
raise ValueError("Couldn't get the key vault properties from properties file")
# Get secret from a specific keyvault
def getSecretFromKeyVault(self, secretName, keyVault=None):
if keyVault is None:
keyVault=self.key_vault
endpoint = 'https://{0}.vault.azure.net/secrets/{1}?api-version=2015-06-01'.format(keyVault, secretName)
headers = {"Authorization": 'Bearer ' + self.access_token}
response = requests.get(endpoint,headers=headers).json()
if 'value' in response:
return response['value']
else:
raise ValueError("Value not found in response")