Rancher API: Unauthorized 401: must authenticate - python

I'm trying to communicate with rancher API, tried different combinations, getting the same result every time:Unauthorized 401: must authenticate
steps to reproduce:
1)Create Rancher API key and secret
2)Create a simple script that uses them to deploy a test workload.
import requests
api_url = "https://myrancherurl.com/v3/project/c-m-qh7tkqn4/jobs"
access_key = "token-zmdpqs"
secret_key = "fr9v6z9xxfqdgmjv2k9z44zvx6mlrandomtoke"
token=access_key+":"+secret_key
# Set the API token
headers = { "Authorization": "Bearer "+token }
# Set the payload for the API request
payload = {
"name": "my-job",
"jobConfig": {
"image": "nginx:latest",
"command": ["nginx", "-g", "daemon off;"],
"restartPolicy": {
"name": "Never"
}
}
}
# Send the API request to create the job
response = requests.post(api_url, json=payload, headers=headers)
# Print the API response
print(response.json())
I'm not 100% sure what exaclty is "Project id", so I tried different combinations, results are the same. I have the impression, that additional config has to be done on rancher side, but can't find any info.
Any ideas?
I've tried also using the official python library, but it seems outdated(and also returns the same erro)

Every object in the Rancher API has an id. Project is a like a group used to organize various namespaces, and workloads.
There are three types of clients that are used to interact with the Rancher API.
Management (Used to interact with general objects not tied to any cluster/project)
Cluster (Used to interact with objects that are tied to a specific cluster)
Project (Used to interact with objects that are tied to a specific project)
Sample code:
pip install git+https://github.com/rancher/client-python.git#master
import rancher
rancher_url = 'https://rancher.example.com/v3'
rancher_token = 'token-abcde:abcdefghijklmnopqrstuvwxyz0123456789'
rancher_verify_ssl_certs = True
management_client = rancher.Client(
url=rancher_url,
token=rancher_token,
verify=rancher_verify_ssl_certs
)
clusters_info = management_client.list_cluster(name='leo-downstream')
my_cluster = clusters_info.data[0]
projects_info = management_client.list_project(name='Default')
default_project = projects_info.data[0]
default_project_url = default_project.links['self'] + '/schemas'
default_project_client = rancher.Client(url=default_project_url, token=rancher_token, verify=False)
containers = [
{
'name': 'one',
'image': 'nginx',
}
]
default_project_client.create_workload(
name='test-workload-creation',
namespaceId='default',
scale=1,
containers=containers
)

Related

APNS Notifications: Python HTTP/2 POST request returning 404 ({"reason":"BadPath"})

I am developing a watchOS app and I want to send push notifications to my users. I have enabled "Push Notifications" in signing and capabilities and a file called "app_name WatchKit Extension" was generated containing one entitlement called APS environment whose value is set to "development".
I have also generated a .p8 file in the Apple Developer Website with the authentication key and that also gives me the key id.
I have created a Swift class called App Delegate that conforms to UNUserNotificationCenterDelegate. I have implemented the method applicationDidFinishLaunching from where I call WKExtension.shared().registerForRemoteNotifications(). Then I implemented the didRegisterForRemoteNotifications where I receive the device token and convert it into a string by executing these lines of code:
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
Then I send the token to the server. In the server I have a Python script that makes the post request to https://api.sandbox.push.apple.com:443 with the headers and notification payload. However, I always get a 404 error ({"reason":"BadPath"}).
I don't know what I am doing wrong. Am I configuring anything wrong? This is the Python script I am using:
import time
import httpx
import asyncio
import jwt
ALGORITHM = 'ES256'
APNS_AUTH_KEY = "path to .p8 file"
f = open(APNS_AUTH_KEY)
secret = f.read()
apns_token = jwt.encode(
{
'iss': 'cert_id',
'iat': time.time()
},
secret,
algorithm=ALGORITHM,
headers={
'alg':ALGORITHM,
'kid':'key_id'
}
)
dev_server = "https://api.sandbox.push.apple.com:443"
device_token = "9fe2814b6586bbb683b1a3efabdbe1ddd7c6918f51a3b83e90fce038dc058550"
headers = {
'method': 'POST',
'path': '/3/device/{0}'.format(device_token),
'autorization': 'bearer {0}'.format(apns_token),
'apns-push-type': 'myCategory',
'apns-expiration': '0',
'apns-priority': '10',
}
payload = {
"aps" : {
"alert" : {
"title" : "Hello Push",
"message": "This is a notification!"
},
"category": "myCategory"
}
}
async def test():
async with httpx.AsyncClient(http2=True) as client:
client = httpx.AsyncClient(http2=True)
r = await client.post(dev_server, headers=headers, data=payload)
print(r.text)
print(r)
asyncio.run(test())
Is there anything wrong with the way I am setting things up or performing the post request?
Thank you for your help!

How to set the Doc Id with Firebase REST API

Is there a way to manually create a docId when inserting a document into Firestore?
The following Python3 code will insert a new document in Firestore with an auto-generated docId.
import requests
import json
project_id = 'MY_PROJECT_NAME'
web_api_key = 'MY_WEB_API_KEY'
collection_name = 'MY_COLLECTION_NAME'
url = f'https://firestore.googleapis.com/v1/projects/{project_id}/databases/(default)/documents/{collection_name}/?key={web_api_key}'
payload = {
'fields': {
'title': { 'stringValue': 'myTitle' },
'category': { 'stringValue': 'myCat' },
'temperature': { 'doubleValue': 75 }
}
}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
response = requests.post(url, data=json.dumps(payload), headers=headers)
response_dict = json.loads(response.content)
for i in response_dict:
print(f'{i}: {response_dict[i]}')
In case anyone else wants to use this code in the future, to get a Web API key, go to Google Cloud Platform > APIs & Services > Credentials > Create Credentials > API key, then copy the value it generates here.
Thanks,
Ryan
answered in Google Cloud Firestore REST API createDocument auto genarates ID documentId should be added as a query parameter when document is created
So for the code in the question, just url should be changed with the same body:
url = f'https://firestore.googleapis.com/v1/projects/{project_id}/databases/(default)/documents/{collection_name}?documentId={your_custom_doc_id}&key={web_api_key}'
To set a custom document ID, you only need to append the name to the URL path after the respective collection. This is similar to how the document reference works where the path must point to the desired location.
From the documentation:
https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/cities/LA

Updating Azure Container Registry Public Access IP with Python

I've tried looking online but could not find an answer as the documentation (and the API) for Azure Python SDK is just horrible.
I have a Container Registery on Azure with a list of allowed IPs for public access. I'd like to modify that list by adding a new IP using Python.
I'm not sure the API supports it or how to achieve this using ContainerRegistryManagementClient.
Can't agree more that documentation (and the API) for Azure Python SDK is just horrible :)
If you want to add a list of allowed IPs for public access to your Container Registery on Azure, just try the code below using REST API:
from azure.identity import ClientSecretCredential
import requests
TENANT_ID= ""
CLIENT_ID = ""
CLIENT_SECRET = ""
SUBSCRIPTION_ID = ""
GROUP_NAME = ""
REGISTRIES = ""
#your public ip list here
ALLOWED_IPS = [{
"value": "167.220.255.1"
},
{
"value": "167.220.255.2"
}
]
clientCred = ClientSecretCredential(TENANT_ID,CLIENT_ID,CLIENT_SECRET)
authResp = clientCred.get_token("https://management.azure.com/.default")
requestURL = 'https://management.azure.com/subscriptions/'+SUBSCRIPTION_ID+'/resourceGroups/'+GROUP_NAME+'/providers/Microsoft.ContainerRegistry/registries/'+REGISTRIES+'?api-version=2020-11-01-preview'
requestBody = {
"properties": {
"publicNetworkAccess": "Enabled",
"networkRuleSet": {
"defaultAction": "Deny",
"virtualNetworkRules": [],
"ipRules": ALLOWED_IPS
},
"networkRuleBypassOptions": "AzureServices"
}
}
r = requests.patch(url=requestURL,json=requestBody,headers={"Authorization":"Bearer "+ authResp.token})
print(r.text)
Result:
Before you run this, pls make sure that your client app has been granted the required permissions(Azure subscription roles, such as contributor).

Microsoft Graph API update user authentication method - Access Denied

I'm creating an application in Azure AD as a daemon to get user phone
authentication methods using the python msal library and calling the following following endpoint GET https://graph.microsoft.com/beta/users/{id | UPN}/authentication/phoneMethods but i get the following error
{
"error": {
"code": "accessDenied",
"message": "Request Authorization failed",
"innerError": {
"message": "Request Authorization failed",
"date": "2020-11-19T19:26:28",
"request-id": "11975e07-ee6b-4bd2-9a74-7c175c5da560",
"client-request-id": "11975e07-ee6b-4bd2-9a74-7c175c5da560"
}
}
}
My app has the required application permissions to get the info i'm looking for, which are UserAuthenticationMethod.Read.All and UserAuthenticationMethod.ReadWrite.All and it already works with different end points such as GET https://graph.microsoft.com/beta/users/{id | UPN}, this is the code i'm using in order to get the access token required and call the graph api
import json
import logging
import requests
import msal
config = {
"authority": "https://login.microsoftonline.com/TENANT_NAME",
"client_id": "APP_ID",
"scope": ["https://graph.microsoft.com/.default"],
"secret": "APP_SECRET",
"endpoint": "https://graph.microsoft.com/beta/users/{USER_ID}/authentication/phoneMethods"
}
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
)
result = None
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
result = app.acquire_token_for_client(scopes=config["scope"])
if "access_token" in result:
graph_data = requests.get(
config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
print("Graph API call result: ")
print(json.dumps(graph_data, indent=2))
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
i tried to do the same thing using curl or postman and i get the exact same error, so i'm guessing it's an access token issue maybe ?
Thanks in advance
The api call does not support application permissions. You need to grant delegated permissions to the application, and then use the auth code flow to obtain the token.

Azure Analysis rest api : 401 Unauthorized. "Authentication failed."

I'm trying to make a data partition refresh (post) following this azure documentation : https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-async-refresh
Either with post or get I got 401 Unauthorized (Even when the service is Off !).
I got the token from azure AD (ServicePrincipalCredential).
I added the AD as Analysis Services Admins (https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-server-admins)
I gave the owner role to AD in Analysis Services IAM.
it worked with Analysis Services management rest api (https://learn.microsoft.com/en-us/rest/api/analysisservices/operations/list) With the same authentification (got code response 200)
My python code :
from azure.common.credentials import ServicePrincipalCredentials
import requests
credentials = ServicePrincipalCredentials(client_id="ad_client_id",
secret="ad_secret",
tenant="ad_tenant")
token = credentials.token
url = "https://westeurope.asazure.windows.net/servers/{my_server}/models/{my_model}/refreshes"
test_refresh = {
"Type": "Full",
"CommitMode": "transactional",
"MaxParallelism": 1,
"RetryCount": 1,
"Objects": [
{
"table": "my_table",
"partition": "my_partition"
}
]
}
header={'Content-Type':'application/json', 'Authorization': "Bearer {}".format(token['access_token'])}
r = requests.post(url=url, headers=header, data=test_refresh)
import json
print(json.dumps(r.json(), indent=" "))
Response I got :
{
"code": "Unauthorized",
"subCode": 0,
"message": "Authentication failed.",
"timeStamp": "2019-05-22T13:39:03.0322998Z",
"httpStatusCode": 401,
"details": [
{
"code": "RootActivityId",
"message": "aab22348-9ba7-42c9-a317-fbc231832f75"
}
]
}
I'm hopeless, could you please give me somes help to make this clear ?
Finally I resolved the issue.
I had wrong token. The api expect an OAuth2.0 authentification token (The Azure analysis services rest api documentation ins't very clear about the way to get one)
For thoses will encounter the same issu there is the way to get one.
from adal import AuthenticationContext
authority = "https://login.windows.net/{AD_tenant_ID}"
auth_context = AuthenticationContext(authority)
oauth_token = auth_context.acquire_token_with_client_credentials(resource="https://westeurope.asazure.windows.net", client_id=AD_client_id, client_secret=AD_client_id)
token = oauth_token['accessToken']
Documentation about this :
https://learn.microsoft.com/en-us/python/api/adal/adal.authentication_context.authenticationcontext?view=azure-python#acquire-token-with-client-credentials-resource--client-id--client-secret-
https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/ADAL-basics
Most likely your token is not right.
Have you tried validating your token? Use something like http://calebb.net/
I see some examples of ServicePrincipalCredentials that stipulate the context or resource like this:
credentials = ServicePrincipalCredentials(
tenant=options['tenant_id'],
client_id=options['script_service_principal_client_id'],
secret=options['script_service_principal_secret'],
resource='https://graph.windows.net'
Good samples here:
https://www.programcreek.com/python/example/103446/azure.common.credentials.ServicePrincipalCredentials
I think the solution is try a couple more things that make sense and follow the error details.
You need token which has resource (audience) set to https://*.asazure.windows.net
For token validation I like https://jwt.io
Also if you want to automate this properly you have two options
Either by Logic Apps
or with Azure Data Factory
Both of which I have very detailed posts on if you want to check them out
https://marczak.io/posts/2019/06/logic-apps-refresh-analysis-services/
https://marczak.io/posts/2019/06/logic-app-vs-data-factory-for-aas-refresh/

Categories

Resources