I have a Django app created using Django rest framework. Below is the configuration that my setup is using:
Django 1.9
mongoDB as backend
gunicorn
nginx
Now I have created an API to enter data in DB and retrieve it using REST. I have test it via postman and it is working fine. We have a firmware which is consuming those APIs and that team want to use SSL socket connection instead of REST API.
I am new in SSL Socket connection and I am not able to find anything on internet that can help me on this. I know it is possible to create socket in Python but I am not able to understand how to use it in Django app to Read/Write data in mongoDB.
Any guidance will be very helpful.
TO READER : I understand you may want to close this question but please put up a remark on how to get guidance on this as SO is the biggest portal for putting up questions.
EDIT 1 : I am adding the code of my serializer.py API.
from rest_framework import serializers
class SaveUserLogs(serializers.Serializer):
token = serializers.CharField(label=_("Token"))
device_ip = serializers.CharField(label=_('Device IP'))
device_name = serializers.CharField(label=_('Device Name'))
device_os = serializers.CharField(label=_('Device OS'))
device_macid = serializers.CharField(label=_('Device MAC ID'))
dest_port = serializers.CharField(label=_('Device Port'))
conn_type = serializers.CharField(label=_('Connection Type'))
date = serializers.CharField(label=_('modified date'))
def validate(self, attrs):
device_macid = attrs.get('device_macid')
token = attrs.get('token')
if device_macid:
tokendetails = validate_token(token)
if not tokendetails:
msg = _('Invalid token.')
raise serializers.ValidationError(msg)
else:
userdetails = tokendetails.user
if userdetails.check_mac_id(device_macid):
all_logs = UserLog.objects.all().order_by("-id")
log_id = 1
if all_logs:
getid = all_logs[0].id
log_id = getid + 1
new_log = UserLog(
id=log_id,
device_ip=attrs.get('device_ip'),
device_name=attrs.get('device_name'),
device_os=attrs.get('device_os'),
device_macid=attrs.get('device_macid').upper(),
dest_port=attrs.get('dest_port'),
conn_type=attrs.get('conn_type'),
)
new_log.save()
print("saving log", log_id)
else:
msg = _('Invalid MAC ID')
raise serializers.ValidationError(msg)
else:
msg = _('Must include "MAC ID".')
raise serializers.ValidationError(msg)
attrs['mac_id'] = userdetails.mac_id
return attrs
It looks like you require socket library provided with python. But using this is not recommended since you will have to take care of lot of low level networking stuff and your program will get complicated.
You should instead keep your REST api and run your nginx server on https. You can then write the code on firmware to send and receive data from the server using https.
If for some reason you don't want to use https then you should use requests library to write your server.
Related
I'm trying to upgrade a legacy mail bot to authenticate via Oauth2 instead of Basic authentication, as it's now deprecated two days from now.
The document states applications can retain their original logic, while swapping out only the authentication bit
Application developers who have built apps that send, read, or
otherwise process email using these protocols will be able to keep the
same protocol, but need to implement secure, Modern authentication
experiences for their users. This functionality is built on top of
Microsoft Identity platform v2.0 and supports access to Microsoft 365
email accounts.
Note I've explicitly chosen the client credentials flow, because the documentation states
This type of grant is commonly used for server-to-server interactions
that must run in the background, without immediate interaction with a
user.
So I've got a python script that retrieves an Access Token using the MSAL python library. Now I'm trying to authenticate with the IMAP server, using that Access Token. There's some existing threads out there showing how to connect to Google, I imagine my case is pretty close to this one, except I'm connecting to a Office 365 IMAP server. Here's my script
import imaplib
import msal
import logging
app = msal.ConfidentialClientApplication(
'client-id',
authority='https://login.microsoftonline.com/tenant-id',
client_credential='secret-key'
)
result = app.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])
def generate_auth_string(user, token):
return 'user=%s\1auth=Bearer %s\1\1' % (user, token)
# IMAP time!
mailserver = 'outlook.office365.com'
imapport = 993
M = imaplib.IMAP4_SSL(mailserver,imapport)
M.debug = 4
M.authenticate('XOAUTH2', lambda x: generate_auth_string('user#mydomain.com', result['access_token']))
print(result)
The IMAP authentication is failing and despite setting M.debug = 4, the output isn't very helpful
22:56.53 > b'DBDH1 AUTHENTICATE XOAUTH2'
22:56.53 < b'+ '
22:56.53 write literal size 2048
22:57.84 < b'DBDH1 NO AUTHENTICATE failed.'
22:57.84 NO response: b'AUTHENTICATE failed.'
Traceback (most recent call last):
File "/home/ubuntu/mini-oauth.py", line 21, in <module>
M.authenticate("XOAUTH2", lambda x: generate_auth_string('user#mydomain.com', result['access_token']))
File "/usr/lib/python3.10/imaplib.py", line 444, in authenticate
raise self.error(dat[-1].decode('utf-8', 'replace'))
imaplib.IMAP4.error: AUTHENTICATE failed.
Any idea where I might be going wrong, or how to get more robust information from the IMAP server about why the authentication is failing?
Things I've looked at
Note this answer no longer works as the suggested scopes fail to generate an Access Token.
The client credentials flow seems to mandate the https://graph.microsoft.com/.default grant. I'm not sure if that includes the scope required for the IMAP resource
https://outlook.office.com/IMAP.AccessAsUser.All?
Verified the code lifted from the Google thread produces the SASL XOAUTH2 string correctly, per example on the MS docs
import base64
user = 'test#contoso.onmicrosoft.com'
token = 'EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA'
xoauth = "user=%s\1auth=Bearer %s\1\1" % (user, token)
xoauth = xoauth.encode('ascii')
xoauth = base64.b64encode(xoauth)
xoauth = xoauth.decode('ascii')
xsanity = 'dXNlcj10ZXN0QGNvbnRvc28ub25taWNyb3NvZnQuY29tAWF1dGg9QmVhcmVyIEV3QkFBbDNCQUFVRkZwVUFvN0ozVmUwYmpMQldaV0NjbFJDM0VvQUEBAQ=='
print(xoauth == xsanity) # prints True
This thread seems to suggest multiple tokens need to be fetched, one for graph, then another for the IMAP connection; could that be what I'm missing?
Try the below steps.
For Client Credentials Flow you need to assign “Application permissions” in the app registration, instead of “Delegated permissions”.
Add permission “Office 365 Exchange Online / IMAP.AccessAsApp” (application).
Grant admin consent to you application
Service Principals and Exchange.
Once a service principal is registered with Exchange Online, administrators can run the Add-Mailbox Permission cmdlet to assign receive permissions to the service principal.
Use scope 'https://outlook.office365.com/.default'.
Now you can generate the SALS authentication string by combining this access token and the mailbox username to authenticate with IMAP4.
#Python code
def get_access_token():
tenantID = 'abc'
authority = 'https://login.microsoftonline.com/' + tenantID
clientID = 'abc'
clientSecret = 'abc'
scope = ['https://outlook.office365.com/.default']
app = ConfidentialClientApplication(clientID,
authority=authority,
client_credential = clientSecret)
access_token = app.acquire_token_for_client(scopes=scope)
return access_token
def generate_auth_string(user, token):
auth_string = f"user={user}\1auth=Bearer {token}\1\1"
return auth_string
#IMAP AUTHENTICATE
imap = imaplib.IMAP4_SSL(imap_host, 993)
imap.debug = 4
access_token = get_access_token_to_authenticate_imap()
imap.authenticate("XOAUTH2", lambda x:generate_auth_string(
'useremail',
access_token['access_token']))
imap.select('inbox')
The imaplib.IMAP4.error: AUTHENTICATE failed Error occured because one point in the documentation is not that clear.
When setting up the the Service Principal via Powershell you need to enter the App-ID and an Object-ID. Many people will think, it is the Object-ID you see on the overview page of the registered App, but its not!
At this point you need the Object-ID from "Azure Active Directory -> Enterprise Applications --> Your-App --> Object-ID"
New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]
Microsoft says:
The OBJECT_ID is the Object ID from the Overview page of the
Enterprise Application node (Azure Portal) for the application
registration. It is not the Object ID from the Overview of the App
Registrations node. Using the incorrect Object ID will cause an
authentication failure.
Ofcourse you need to take care for the API-permissions and the other stuff, but this was for me the point.
So lets go trough it again, like it is explained on the documentation page.
Authenticate an IMAP, POP or SMTP connection using OAuth
Register the Application in your Tenant
Setup a Client-Key for the application
Setup the API permissions, select the APIs my organization uses tab and search for "Office 365 Exchange Online" -> Application permissions -> Choose IMAP and IMAP.AccessAsApp
Setup the Service Principal and full access for your Application on the mailbox
Check if IMAP is activated for the mailbox
Thats the code I use to test it:
import imaplib
import msal
import pprint
conf = {
"authority": "https://login.microsoftonline.com/XXXXyourtenantIDXXXXX",
"client_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX", #AppID
"scope": ['https://outlook.office365.com/.default'],
"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", #Key-Value
"secret-id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", #Key-ID
}
def generate_auth_string(user, token):
return f"user={user}\x01auth=Bearer {token}\x01\x01"
if __name__ == "__main__":
app = msal.ConfidentialClientApplication(conf['client_id'], authority=conf['authority'],
client_credential=conf['secret'])
result = app.acquire_token_silent(conf['scope'], account=None)
if not result:
print("No suitable token in cache. Get new one.")
result = app.acquire_token_for_client(scopes=conf['scope'])
if "access_token" in result:
print(result['token_type'])
pprint.pprint(result)
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
imap = imaplib.IMAP4('outlook.office365.com')
imap.starttls()
imap.authenticate("XOAUTH2", lambda x: generate_auth_string("target_mailbox#example.com", result['access_token']).encode("utf-8"))
After setting up the Service Principal and giving the App full access on the mailbox, wait 15 - 30 minutes for the changes to take effect and test it.
Try with this script:
import json
import msal
import requests
client_id = '***'
client_secret = '***'
tenant_id = '***'
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=authority)
scopes = ["https://graph.microsoft.com/.default"]
result = None
result = app.acquire_token_silent(scopes, account=None)
if not result:
print(
"No suitable token exists in cache. Let's get a new one from Azure Active Directory.")
result = app.acquire_token_for_client(scopes=scopes)
# if "access_token" in result:
# print("Access token is " + result["access_token"])
if "access_token" in result:
userId = "***"
endpoint = f'https://graph.microsoft.com/v1.0/users/{userId}/sendMail'
toUserEmail = "***"
email_msg = {'Message': {'Subject': "Test Sending Email from Python",
'Body': {'ContentType': 'Text', 'Content': "This is a test email."},
'ToRecipients': [{'EmailAddress': {'Address': toUserEmail}}]
},
'SaveToSentItems': 'true'}
r = requests.post(endpoint,
headers={'Authorization': 'Bearer ' + result['access_token']}, json=email_msg)
if r.ok:
print('Sent email successfully')
else:
print(r.json())
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id"))
Source: https://kontext.tech/article/795/python-send-email-via-microsoft-graph-api
I am trying to deploy resources to Azure China with ARM Templates. I had the code to do it for Azure, and now I am adapting it for Azure China, I believe that the only changes that I should perform were in
Change the authority host in the credentials
self.credentials = DefaultAzureCredential(authority = AzureAuthorityHosts.AZURE_CHINA)
Change the Management Url in the Client.
endpoints = get_cloud_from_metadata_endpoint(os.environ.get("ARM_ENDPOINT"))
self.client = ResourceManagementClient(self.credentials, self.subscriptionId, base_url=endpoints.endpoints.resource_manager)
Below is the code that I am using
Python Code:
def __init__(self, subscriptionId, resourceGroup):
self.logger = Logger("Azure China Connection")
self.logger.info("Retrieving the list of available endpoint")
# ARM_ENDPOINT = https://management.chinacloudapi.cn
endpoints = get_cloud_from_metadata_endpoint(os.environ.get("ARM_ENDPOINT"))
self.subscriptionId = subscriptionId
self.resourceGroup = resourceGroup
self.credentials = DefaultAzureCredential(authority = AzureAuthorityHosts.AZURE_CHINA)
self.logger.info("Creating a client for deploying resources on subscription {}".format(self.subscriptionId))
self.client = ResourceManagementClient(self.credentials, self.subscriptionId,
# endpoints.endpoints.resource_manager = https://management.chinacloudapi.cn
base_url=endpoints.endpoints.resource_manager)
self.logger.success("Client was successfully created")
def deploy(self, template, parameters):
resources = ""
for resource in template.get("resources"):
resources += "\n\t {}".format(resource.get("type"))
self.logger.info("The following resources: {}\nwill be deployed".format(resources))
deploymentProperties = DeploymentProperties(
mode = DeploymentMode.incremental,
template = template,
parameters = parameters.get("parameters")
)
self.logger.info("Attempting deploy operation")
deployment = self.client.deployments.begin_create_or_update(
self.resourceGroup,
uuid7(),
Deployment(properties=deploymentProperties)
) # Error occurs here
self.logger.success("Resources deployment successfully triggered")
return deployment.result()
load_dotenv()
connection = new AzureChinaConnection(os.environ.get("AZURE_SUBSCRIPTION_ID"), os.environ.get("AZURE_RESOURCE_GROUP"))
deployment = self.connection.deploy(template.json(), parameter.json())
**Message=**DefaultAzureCredential failed to retrieve a token from the
included credentials. Attempted credentials: EnvironmentCredential:
Authentication failed: AADSTS500011: The resource principal named
https://management.azure.com was not found in the tenant named EY
CHINA. 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 might have sent your authentication request to the wrong
tenant. Trace ID: ace63d66-af4b-4457-b6c9-6ce050e34700 Correlation ID:
d85942a5-35fb-493f-8eef-ee9fe1f64b7f Timestamp: 2022-09-29 19:44:47Z
To mitigate this issue, please refer to the troubleshooting guidelines
here at
https://aka.ms/azsdk/python/identity/defaultazurecredential/troubleshoot.
Based on the error message, it looks like I am pointing to a wrong endpoint https://management.azure.com instead of https://management.chinacloudapi.cn. The question is, where should I set it?
I though that it was already doing it in the __init__
self.client = ResourceManagementClient(self.credentials, self.subscriptionId,
# endpoints.endpoints.resource_manager = https://management.chinacloudapi.cn
base_url=endpoints.endpoints.resource_manager)
but seems it is not enough.
After struggling a lot, finally found the solution. Seems that no all the properties of Resource Manager Client are listed at:
https://learn.microsoft.com/en-us/python/api/azure-mgmt-resource/azure.mgmt.resource.resources.resourcemanagementclient?view=azure-python
There is a property named credential_scopes which should be set for change
credential_scopes=[CLOUD.endpoints.resource_manager + "/.default"])
so the function looks like
def __init__(self, subscriptionId, resourceGroup):
self.subscriptionId = subscriptionId
self.resourceGroup = resourceGroup
self.credentials = DefaultAzureCredential()
self.logger.info("Creating a client for deploying resources on subscription {}".format(self.subscriptionId))
self.client = ResourceManagementClient(self.credentials, self.subscriptionId,
base_url=CLOUD.endpoints.resource_manager,
credential_scopes=[CLOUD.endpoints.resource_manager + "/.default"])
Im trying to create an aiosmtpd server to process emails received.
It works great without authentication, yet i simply cannot figure out how to setup the authentication.
I have gone through the documents and searched for examples on this.
a sample of how im currently using it:
from aiosmtpd.controller import Controller
class CustomHandler:
async def handle_DATA(self, server, session, envelope):
peer = session.peer
mail_from = envelope.mail_from
rcpt_tos = envelope.rcpt_tos
data = envelope.content # type: bytes
# Process message data...
print('peer:' + str(peer))
print('mail_from:' + str(mail_from))
print('rcpt_tos:' + str(rcpt_tos))
print('data:' + str(data))
return '250 OK'
if __name__ == '__main__':
handler = CustomHandler()
controller = Controller(handler, hostname='192.168.8.125', port=10025)
# Run the event loop in a separate thread.
controller.start()
# Wait for the user to press Return.
input('SMTP server running. Press Return to stop server and exit.')
controller.stop()```
which is the basic method from the documentation.
could someone please provide me with an example as to how to do simple authentication?
Alright, since you're using version 1.3.0, you can follow the documentation for Authentication.
A quick way to start is to create an "authenticator function" (can be a method in your handler class, can be standalone) that follows the Authenticator Callback guidelines.
A simple example:
from aiosmtpd.smtp import AuthResult, LoginPassword
auth_db = {
b"user1": b"password1",
b"user2": b"password2",
b"user3": b"password3",
}
# Name can actually be anything
def authenticator_func(server, session, envelope, mechanism, auth_data):
# For this simple example, we'll ignore other parameters
assert isinstance(auth_data, LoginPassword)
username = auth_data.login
password = auth_data.password
# If we're using a set containing tuples of (username, password),
# we can simply use `auth_data in auth_set`.
# Or you can get fancy and use a full-fledged database to perform
# a query :-)
if auth_db.get(username) == password:
return AuthResult(success=True)
else:
return AuthResult(success=False, handled=False)
Then you're creating the controller, create it like so:
controller = Controller(
handler,
hostname='192.168.8.125',
port=10025,
authenticator=authenticator_func, # i.e., the name of your authenticator function
auth_required=True, # Depending on your needs
)
I'm having an issue retrieving an Azure Managed Identity access token from my Function App. The function gets a token then accesses a Mysql database using that token as the password.
I am getting this response from the function:
9103 (HY000): An error occurred while validating the access token. Please acquire a new token and retry.
Code:
import logging
import mysql.connector
import requests
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
def get_access_token():
URL = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fossrdbms-aad.database.windows.net&client_id=<client_id>"
headers = {"Metadata":"true"}
try:
req = requests.get(URL, headers=headers)
except Exception as e:
print(str(e))
return str(e)
else:
password = req.json()["access_token"]
return password
def get_mysql_connection(password):
"""
Get a Mysql Connection.
"""
try:
con = mysql.connector.connect(
host='<host>.mysql.database.azure.com',
user='<user>#<db>',
password=password,
database = 'materials_db',
auth_plugin='mysql_clear_password'
)
except Exception as e:
print(str(e))
return str(e)
else:
return "Connected to DB!"
password = get_access_token()
return func.HttpResponse(get_mysql_connection(password))
Running a modified version of this code on a VM with my managed identity works. It seems that the Function App is not allowed to get an access token. Any help would be appreciated.
Note: I have previously logged in as AzureAD Manager to the DB and created this user with all privileges to this DB.
Edit: No longer calling endpoint for VMs.
def get_access_token():
identity_endpoint = os.environ["IDENTITY_ENDPOINT"] # Env var provided by Azure. Local to service doing the requesting.
identity_header = os.environ["IDENTITY_HEADER"] # Env var provided by Azure. Local to service doing the requesting.
api_version = "2019-08-01" # "2018-02-01" #"2019-03-01" #"2019-08-01"
CLIENT_ID = "<client_id>"
resource_requested = "https%3A%2F%2Fossrdbms-aad.database.windows.net"
# resource_requested = "https://ossrdbms-aad.database.windows.net"
URL = f"{identity_endpoint}?api-version={api_version}&resource={resource_requested}&client_id={CLIENT_ID}"
headers = {"X-IDENTITY-HEADER":identity_header}
try:
req = requests.get(URL, headers=headers)
except Exception as e:
print(str(e))
return str(e)
else:
try:
password = req.json()["access_token"]
except:
password = str(req.text)
return password
But now I am getting this Error:
{"error":{"code":"UnsupportedApiVersion","message":"The HTTP resource that matches the request URI 'http://localhost:8081/msi/token?api-version=2019-08-01&resource=https%3A%2F%2Fossrdbms-aad.database.windows.net&client_id=<client_idxxxxx>' does not support the API version '2019-08-01'.","innerError":null}}
Upon inspection this seems to be a general error. This error message is propagated even if it's not the underlying issue. Noted several times in Github.
Is my endpoint correct now?
For this problem, it was caused by the wrong endpoint you request for the access token. We can just use the endpoint http://169.254.169.254/metadata/identity..... in azure VM, but if in azure function we can not use it.
In azure function, we need to get the IDENTITY_ENDPOINT from the environment.
identity_endpoint = os.environ["IDENTITY_ENDPOINT"]
The endpoint is like:
http://127.0.0.1:xxxxx/MSI/token/
You can refer to this tutorial about it, you can also find the python code sample in the tutorial.
In my function code, I also add the client id of the managed identity I created in the token_auth_uri but I'm not sure if the client_id is necessary here (In my case, I use user-assigned identity but not system-assigned identity).
token_auth_uri = f"{identity_endpoint}?resource={resource_uri}&api-version=2019-08-01&client_id={client_id}"
Update:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
string resource="https://ossrdbms-aad.database.windows.net";
string clientId="xxxxxxxx";
log.LogInformation("C# HTTP trigger function processed a request.");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}/?resource={1}&api-version=2019-08-01&client_id={2}", Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT"), resource,clientId));
request.Headers["X-IDENTITY-HEADER"] = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader streamResponse = new StreamReader(response.GetResponseStream());
string stringResponse = streamResponse.ReadToEnd();
log.LogInformation("test:"+stringResponse);
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
For your latest issue, where you are seeing UnsupportedApiVersion, it is probably this issue: https://github.com/MicrosoftDocs/azure-docs/issues/53726
Here are a couple of options that worked for me:
I am assuming you are hosting the Function app on Linux. I noticed that ApiVersion 2017-09-01 works, but you need to make additional changes (instead of "X-IDENTITY-HEADER", use "secret" header). And also use a system-assigned managed identity for your function app, and not a user assigned identity.
When I hosted the function app on Windows, I didn't have the same issues. So if you want to use an user-assigned managed identity, you can try this option instead. (with the api-version=2019-08-01, and X-IDENTITY-HEADER.
My current task is to do QA Automation on our web app, but I don't want to use real credentials for it (for which we use a LDAP server). My idea was to mock the LDAP server when the web app is in TEST_MODE, and to my luck I found out that 'ldap3' (the python module) that we use for authentication, also supports a mocking function. An example code is here:
from ldap3 import Server, Connection, ALL, ALL_ATTRIBUTES, MOCK_SYNC
REAL_SERVER = 'my_real_server'
REAL_USER = 'cn=my_real_user,ou=test,o=lab'
REAL_PASSWORD = 'my_real_password'
# Retrieve server info and schema from a real server
server = Server(REAL_SERVER, get_info=ALL)
connection = Connection(server, REAL_USER, REAL_PASSWORD, auto_bind=True)
# Store server info and schema to json files
server.info.to_file('my_real_server_info.json')
server.schema.to_file('my_real_server_schema.json')
# Read entries from a portion of the DIT from real server and store them in a json file
if connection.search('ou=test,o=lab', '(objectclass=*)', attributes=ALL_ATTRIBUTES):
connection.response_to_file('my_real_server_entries.json', raw=True)
# Close the connection to the real server
connection.unbind()
# Create a fake server from the info and schema json files
fake_server = Server.from_definition('my_fake_server', 'my_real_server_info.json', 'my_real_server_schema.json')
# Create a MockSyncStrategy connection to the fake server
fake_connection = Connection(fake_server, user='cn=my_user,ou=test,o=lab', password='my_password', client_strategy=MOCK_SYNC)
# Populate the DIT of the fake server
fake_connection.strategy.entries_from_json('my_real_server_entries.json')
# Add a fake user for Simple binding
fake_connection.strategy.add_entry('cn=my_user,ou=test,o=lab', {'userPassword': 'my_password', 'sn': 'user_sn', 'revision': 0})
# Bind to the fake server
fake_connection.bind()
I followed this example with our code, and was successful halfway through it. I extracted the real_server_entries in a json file, and now is part to do the fake connection. So to summarise everything is done until this part:
# Create a MockSyncStrategy connection to the fake server
fake_connection = Connection(fake_server, user='cn=my_user,ou=test,o=lab', password='my_password', client_strategy=MOCK_SYNC)
I am not really sure what to put in the place of user and password.
A part of my code:
_USER_SEARCH_FILTER = "(&(objectClass=user)(cn={}))"
_ALL_USERS_SEARCH_FILTER = "(&(objectCategory=person)(objectClass=user))"
_EMAIL_ATTRIBUTE = "mail"
_DISPLAY_NAME_ATTRIBUTE = "displayName"
_USERNAME_ATTRIBUTE = "cn"
_SEARCH_ATTRIBUTES = (
_EMAIL_ATTRIBUTE, _DISPLAY_NAME_ATTRIBUTE, _USERNAME_ATTRIBUTE)
_LDAP_CONNECTION_ERROR = "Connection to LDAP server %s:%s failed: %s"
_LDAP_SERVER = Server(host=LDAP.host, port=int(LDAP.port), get_info='ALL')
server = _LDAP_SERVER
_CONNECTION = Connection(
server,
LDAP.manager_dn, LDAP.manager_password,
auto_bind=True, client_strategy=RESTARTABLE
)
server.info.to_file('my_real_server_info.json')
server.schema.to_file('my_real_server_schema.json')
if _CONNECTION.search(LDAP.root_dn, _ALL_USERS_SEARCH_FILTER, attributes=_SEARCH_ATTRIBUTES):
_CONNECTION.response_to_file('my_real_server_entries.json', raw=True)
_CONNECTION.unbind()
mock_server = Server.from_definition('mock_server', 'my_real_server_info.json', 'my_real_server_schema.json')
mock_connection = Connection(mock_server, user='???', password='???', client_strategy=MOCK_SYNC)
mock_connection.strategy.entries_from_json('my_real_server_entries.json')
mock_connection.strategy.add_entry('LDAP.root_dn', { #My guess is that here I mock the attributes, but this is also the other problem I am having (check below) })
The other problem I have is that I am not even sure if I can add a fake user, because when I took a look into the real_entries.json file the password is not stored there as an attribute (not even an encrypted version of it) and the only attributes we have are:
`cn` - username
`displayName` - LASTNAME, FIRSTNAME
`mail` - example#mail.com