{"id":47595019,"url":"https://github.com/tranquilit/azureadconnect_samba4","last_synced_at":"2026-04-01T18:00:57.957Z","repository":{"id":155515317,"uuid":"595320977","full_name":"tranquilit/AzureADConnect_Samba4","owner":"tranquilit","description":"Azure Ad Connect (Microsoft Entra Connect) for Samba4","archived":false,"fork":false,"pushed_at":"2026-03-18T17:06:38.000Z","size":208,"stargazers_count":46,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-19T06:51:58.791Z","etag":null,"topics":["azuread","azureadconnect","python3","samba","samba4"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tranquilit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-30T21:00:36.000Z","updated_at":"2026-03-18T17:25:49.000Z","dependencies_parsed_at":"2023-05-02T22:53:56.444Z","dependency_job_id":"dd203373-735d-4af5-aedc-f53f1dd6e070","html_url":"https://github.com/tranquilit/AzureADConnect_Samba4","commit_stats":null,"previous_names":["tranquilit/azureadconnect_samba4"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tranquilit/AzureADConnect_Samba4","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tranquilit%2FAzureADConnect_Samba4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tranquilit%2FAzureADConnect_Samba4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tranquilit%2FAzureADConnect_Samba4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tranquilit%2FAzureADConnect_Samba4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tranquilit","download_url":"https://codeload.github.com/tranquilit/AzureADConnect_Samba4/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tranquilit%2FAzureADConnect_Samba4/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290740,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azuread","azureadconnect","python3","samba","samba4"],"created_at":"2026-04-01T18:00:27.263Z","updated_at":"2026-04-01T18:00:57.916Z","avatar_url":"https://github.com/tranquilit.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Notes\n\nIf you use this script and it works correctly - please do not be lazy to put a star. This motivates me very much to develop my product. If you lack some functions, write about it. I will try to add them if they fit into the product concept.\n\n# Install notes\n\n```\napt-get install git\ngit clone --recurse-submodules https://github.com/tranquilit/AzureADConnect_Samba4.git /opt/sync-azure\nmkdir /etc/azureconf/\ncp -f /opt/sync-azure/azure.conf.exemple /etc/azureconf/azure.conf\napt-get install python3-peewee python3-passlib python3-xmltodict python3-requests python3-msal -y\n```\n\n\nIf you are not under debian or if you do not have the packages available :\n\n```\napt-get install python3-pip\npip3 install -r /opt/sync-azure/requirements.txt\npip3 install -r /opt/sync-azure/AADInternals_python/requirements.txt\n```\n\n - Configure /etc/azureconf/azure.conf\n\nYou can try like this:\n\n```\npython3 /opt/sync-azure/run_sync.py\n```\n\nThe script sends all users and groups a first time and then only sends what has been modified since the last send during the next launch. (delta)\n\nTo force a send from all again, use --force (force sync) :\n\n```\npython3 /opt/sync-azure/run_sync.py --force\n```\n\n\u0026#x1F4A1; Once your first full sync has taken place, it's worth changing this setting to True to make the script run much faster. \nThis makes it possible to calculate deletions based on the last send and therefore no longer query Microsoft servers at each launch.\n\n```\ncalculate_deletions_based_on_last_sync=True\n```\n\n# Warning\n\n* Please note that this project uses Microsoft APIs not officially documented. Microsoft may break compatibility at any time\n\n* userPrincipalName is used for the email address (add alternate_login_id_attr=mail in azure.conf to use the mail attribute instead of the userPrincipalName attribute ) [1]\n\n* \"password writeback\" not supported\n\n* User and group management only (device optional)\n\n[1] https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/plan-connect-userprincipalname#alternate-login-id\n\n# sourceanchor\n\nThe default sourceanchor in azure.conf.exemple is the objectGUID with msDSConsistencyGuid! read : https://learn.microsoft.com/en-us/azure/active-directory/hybrid/plan-connect-design-concepts#using-ms-ds-consistencyguid-as-sourceanchor\n\nYou can run the script on a previous installation but you have to pay attention to the previous configuration of your azure ad connect (sourceanchor)\n\n\u003e **\u0026#x26A0;\u0026#xFE0F;Warning**\n\u003e If \"sourceanchor\" changes, it will initiate object deletions and then object recreations. You must therefore choose your sourceanchor well and not change it\n\nA dry_run mode allows you to run the script without making any changes\n\n# advanced configuration\n\n## using specific basedn\n\nYou can specify a specific basedn for search in samba:\n\n```\nbasedn = OU=TEST,DC=MYDOMAIN,DC=LAN\n```\n\nOR a base dn for each type of object:\n\n```\nbasedn_user     = OU=USER,DC=MYDOMAIN,DC=LAN\nbasedn_group    = OU=GROUP,DC=MYDOMAIN,DC=LAN\nbasedn_computer = OU=COMPUTER,DC=MYDOMAIN,DC=LAN\n```\n\nFor precisely several bases dn, separate them with | \n\n```\nbasedn_user     = OU=USER,DC=MYDOMAIN,DC=LAN|OU=USER2,DC=MYDOMAIN,DC=LAN\n```\n\n## custom filter for search\n\nYou can specify a specific custom ldap filter for search in samba:\n\n```\ncustom_filter_user     = (memberof:1.2.840.113556.1.4.1941:=CN=group_users,OU=Groupe,DC=mydomain,DC=lan)\ncustom_filter_group    = (memberof:1.2.840.113556.1.4.1941:=CN=group_groups,OU=Groupe,DC=mydomain,DC=lan)\ncustom_filter_computer = (memberof:1.2.840.113556.1.4.1941:=CN=group_computers,OU=Groupe,DC=mydomain,DC=lan)\n```\n\n## Do not use userPrincipalName as login\n\nYou can specify which attribute should be used as login. Please note this must be an email address. Use alternate_login_id_attr\n\n\n```\nalternate_login_id_attr = mail\n```\n\nMode not recommended, it will cause problems with sso mode because the email is not a login in the kerberos sense.\n\n## other settings\n\n* credential_cache_file :\n\n\nspecifies where the last connection token will be stored and read:\n\n```\ncredential_cache_file = /root/last_token.json\n```\n\n* dbpath :\n\n\nspecifies where the db that stores the state of the last scan will be stored:\n\n```\ndbpath = /root/last_send_azuread.db\n```\n\n* calculate_deletions_based_on_last_sync :\n\ncalculate deletions based on local last sync, does not list the users, groups and devices of the Azure AD to calculate the necessary deletion and will make the comparison with the last send of the script. Much faster mode \n\n```\ncalculate_deletions_based_on_last_sync=True\n```\n\n## Samba configuration\n\nYou can add pathsmbconf and url parameters in the configuration file. \nIf you are using a samba version of the distribution this should not be necessary.\n\n```\nurl         = /usr/local/samba/private/sam.ldb\npathsmbconf = /usr/local/samba/lib/smb.conf\n```\n\n## Use Python callback to modify the calculated result of the script\n\nCopy callback_template:\n\n```\ncp -r /opt/sync-azure/callback_template /root/callbackaad\n```\n\nadd option in config file : \n\n```\nfolder_callback_python = /root/callbackaad\n```\n\nNow edit /root/callbackaad/callbackaadsync.py (do not change the file name)\n\nExemple: \n\n```\ndef callback_calculated_user(sambaobj=None,entry=None,result=None):\n    result['company'] = \"MY ENTERPRISE\"\n    return result\n```\n\nIn this example we force the company entry \"MY ENTERPRISE\" on all user entries\n\n- sambaobj is the already instantiated samdb object, it can be used to do searches\n\n- Entry is user entry returned by samdb\n\n- result is resultcalculated by the script so you can modify it\n\nThe function returns the result modify, if the function returns None, the user will be skipped from the sync\n\n## Use Python callback to run code after sending\n\nIn certain cases we want to execute code in addition to sending it to Azure AD\n\nExemple: Send an email, Enter something into a database, Perform additional actions in Azure AD.\n\nIn this case you can use: callback_after_send_obj and callback_after_send_hashnt\n\nA final callback is called at the end of the sync with callback_end_synchro\n\n## Run the project on a member machine (non-domain controller)\n\nThe machine must have samba installed. (Many samba libraries are required)\n\nAdd in azure.conf add :\n\n```\nurl=ldap://srvads.ad.lan:389\nuser_ad=administrator\npassword_ad=password\n```\nThe specified account must have permission to replicate passwords.\n\nThis operating mode also works with a Microsoft active directory.\n\n\n# compatibility\n\n\nThe first version of this project used the \"objectsid\" string as \"sourceanchor\", this mode now corresponds to an \"objectSID_str\" as sourceanchor in the ini file, this mode does not exist with azure ad microsoft, so it should no longer be used.\n\n# Frequent problems and questions\n\n## Access to Azure Active Directory has been denied\n\nIf the script crashes with this message:\n\n```\n  File \"/opt/sync-azure/AADInternals_python/AADInternals.py\", line 596, in xml_to_result\n    raise Exception(dataxml[\"s:Envelope\"][\"s:Body\"]['s:Fault']['s:Reason']['s:Text']['#text'])\nException: Access to Azure Active Directory has been denied. Contact Technical Support.\n\n```\n\nIt appears that the user you authenticated with does not have the rights to perform the requested actions.\n\nYou can change user by deleting the /root/last_token_azuread.json file and running the script again.\n\n## Log parsing\n\nThe logs are stored in JSON format and, by default, they are stored here: /var/log/azure_ad_sync.\n\nYou can, for example, parse them with jq:\n\n```\ncat /var/log/azure_ad_sync | jq 'select(.type == \"send_nthash\") |  .timestamp, .data.onPremisesSamAccountName '\n```\n\n```\ncat /var/log/azure_ad_sync | jq 'select(.data.onPremisesSamAccountName == \"luke.skywalker\") '\n```\n\n```\ncat /var/log/azure_ad_sync | jq 'select(.data.onPremisesSamAccountName == \"luke.skywalker\") |  .timestamp, .type '\n```\n\n\n## SSLError (SSLCertVerificationError)\n\nIf the script crashes with this message:\n\n```\nSSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:992)')\n```\n\nCertainly you have a firewall that performs SSL inspection.\n\nAdd in azure.conf : \n\n```\nverify=/root/ca.crt\n```\n\n/root/ca.crt is the firewall certificate\n\n\n## Duplicate Attribute resiliency \n\nYou can sometimes with this kind of message:\n\n```\nINFO:root:{\"type\": \"warning_duplicate_mail_value\", \"timestamp\": \"2024-11-11 14:31:04.764566\", \"data\": {\"mail\": \"chewbacca@testoutlook.mail.onmicrosoft.com\", \"list_conflicting_objects\": {\"CN=chewie,CN=Users,DC=mydomain,DC=lan\": [\"proxyAddresses\"], \"CN=chewbacca,CN=Users,DC=mydomain,DC=lan\": [\"userPrincipalName\"]}}}\n```\n\nor \n\n```\nThis object has been updated in your Azure Active Directory, but with some modified properties, because the following attributes are associated with another object [ProxyAddresses \u003cpii\u003eSMTP:chewie@testoutlook.mail.onmicrosoft.com\u003c/pii\u003e;]. Please refer to https://aka.ms/duplicateattributeresiliency for steps on how to resolve this issue.\n```\n\nThis means that two different accounts have the same email address.\n\nIn Active directory : Either by the userPrincipalName attribute, by email or by the proxyAddresses attribute\n\nSometimes the duplicate is in your active directory and you can identify duplicate objects with \"warning_duplicate_mail_value\" in logs.\n\nIf the duplicate is not in your active directory this means that the duplicate is present in \"entra id\" with an account not synchronized with the active directory.\n\nWhen you have resolved the conflicts it may sometimes be necessary to force a synchronization with:\n\n```\npython3 /opt/sync-azure/run_sync.py --force\n```\n\n## When you have an existing tenant\n\nThe explanation here applies to this project :\n\nhttps://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-install-existing-tenant\n\n### Case Azure Administrator Sync\n\nSynchronization does not work with an \"entra id\" administrator account :\n\nsee: https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-install-existing-tenant#admin-role-considerations\n\n* Remove administrator rights from the account in Azure.\n* Start synchronization\n* The account should now go to “local sync enabled”\n* You can now restore the rights previously removed\n* The account is now recognized as a synchronized local account, synchronization works again.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftranquilit%2Fazureadconnect_samba4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftranquilit%2Fazureadconnect_samba4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftranquilit%2Fazureadconnect_samba4/lists"}