MitreID Connect : Retrieve LDAP operational attributes - attributes

I'm working on the LDAP overlay of MitreID Connect project and everthing is working greatly:
Authentication
Retrieving attributes from LDAP Directory
The problem I have now, is how to retrieve operational attributes in LDAP directory.
I'm not good with Spring development, but I found some documentation which treat this sub, but I'm not able to make it work.
Here's what I found:
Retrieving operational attributes
Ldap Server maintains many operational attributes internally. Example entryUUID is an operational attribute assigns the Universally Unique Identifier (UUID) to the entry. The createTimestamp, modifyTimestamp are also operational attributes assigned to the entry on create or update. These operational attributes does not belong to an object class and hence they were not returned as part of your search or lookup. You need to explicitly request them by their name in your search or build the custom AttributeMapper implementation with matching attribute names.
Now let’s try to retrieve the entryUUID, first you need to build the search controls like this,
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningObjFlag(false);
controls.setReturningAttributes(new String[]{"entryUUID"});
Once you have search control then it’s simply calling search method just like retrieving any other attributes.
ldapTemplate.search("baseName", "(objectclass=person)", controls, new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
Attribute attrUuid = attrs.get("entryUUID");
return attrUuid;
}});
Here is another way to do the same using ContextMapper,
ldapTemplate.search("baseName","(objectclass=person)", 1, new String[]{"entryUUID"},
new ContextMapper(){
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter)ctx;
return context.getStringAttributes("entryUUID");
}
});
Let’s add the filter based off of operational attributes like below,
OrFilter orFilter = new OrFilter();
orFilter.or(new GreaterThanOrEqualsFilter("createTimestamp", "YYYYMMDDHHMMSSZ"));
orFilter.or(new LessThanOrEqualsFilter("modifyTimestamp", "YYYYMMDDHHMMSSZ"));
Now call the above search with the filter
ldapTemplate.search("baseName", orFilter.encode(), controls, new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs) throws NamingException {
Attribute attrUuid = attrs.get("entryUUID");
return attrUuid;
}});

Related

Orchard CMS front-end all possible content filtering by user permissions

Good day!
In my Orchard, I have several content types all with my custom part attached. This part defines to what users this content is available. For each logged user there is external service, which defines what content user can or cannot access. Now I need access restriction to apply everywhere where orchard display content lists, this includes results by specific tag from a tag cloud, or results listed from Taxonomy term. I seems can’t find any good way to do it except modifying TaxonomyServices code as well as TagCloud services, to join also my part and filter by it. Is this indeed the only way to do it or there are other solutions? I would like to avoid doing changes to built-in modules if possible but cannot find other way.
Thanks in advance.
I'm currently bumbling around with the same issue. One way I'm currently looking at is to hook into the content manager.
[OrchardSuppressDependency("Orchard.ContentManagement.DefaultContentManager")]
public class ModContentManager : DefaultContentManager, IContentManager
{
//private readonly Lazy<IShapeFactory> _shapeFactory;
private readonly IModAuthContext _modAuthContext;
public ModContentManager(IComponentContext context,
IRepository<ContentTypeRecord> contentTypeRepository,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
IContentDefinitionManager contentDefinitionManager,
ICacheManager cacheManager,
Func<IContentManagerSession> contentManagerSession,
Lazy<IContentDisplay> contentDisplay,
Lazy<ISessionLocator> sessionLocator,
Lazy<IEnumerable<IContentHandler>> handlers,
Lazy<IEnumerable<IIdentityResolverSelector>> identityResolverSelectors,
Lazy<IEnumerable<ISqlStatementProvider>> sqlStatementProviders,
ShellSettings shellSettings,
ISignals signals,
//Lazy<IShapeFactory> shapeFactory,
IModAuthContext modAuthContext)
: base(context,
contentTypeRepository,
contentItemRepository,
contentItemVersionRepository,
contentDefinitionManager,
cacheManager,
contentManagerSession,
contentDisplay,
sessionLocator,
handlers,
identityResolverSelectors,
sqlStatementProviders,
shellSettings,
signals) {
//_shapeFactory = shapeFactory;
_modAuthContext = modAuthContext;
}
public new dynamic BuildDisplay(IContent content, string displayType = "", string groupId = "") {
// So you could do something like...
// var myPart = content.As<MyAuthoPart>();
// if(!myPart.IsUserAuthorized)...
// then display something else or display nothing (I think returning null works for this but
//don't quote me on that. Can always return a random empty shape)
// else return base.BuildDisplay(content, displayType, groupId);
// ever want to display a shape based on the name...
//dynamic shapes = _shapeFactory.Value;
}
}
}
Could also hook into the IAuthorizationServiceEventHandler, which is activated before in the main ItemController and do a check to see if you are rendering a projection or taxonomy list set a value to tell your content manager to perform checks else just let them through. Might help :)

Defalut XmlSiteMapProvider implementation cannot use SiteMap.FindSiteMapNode?

I just upgrade MvcSiteMapProvider from v3 to v4.6.3.
I see the upgrade note indicate:
In general, any reference to System.Web.SiteMap.Provider will need to be updated to MvcSiteMapProvider.SiteMaps.Current
I am trying to get the sitemap node by using:
SiteMaps.Current.FindSiteMapNode(rawUrl)
But it always return null
I looked into the code. In the sitemap it's actually calling the function:
protected virtual ISiteMapNode FindSiteMapNodeFromUrlMatch(IUrlKey urlToMatch)
{
if (this.urlTable.ContainsKey(urlToMatch))
{
return this.urlTable[urlToMatch];
}
return null;
}
It's trying to find a match in the urlTable.
I am using Default implementation of XmlSiteMapProvider .
It define var url = node.GetAttributeValue("url");
siteMapNode.Url = url;
siteMapNode.UrlResolver = node.GetAttributeValue("urlResolver");
So if I did not define url or urlResolver attribute in the .sitemap file. These variables a set to empty string, when generate the node.
And when this nodes are passed to AddNode function in SiteMap.
When adding the node
bool isMvcUrl = string.IsNullOrEmpty(node.UnresolvedUrl) && this.UsesDefaultUrlResolver(node);
this code will check if there is url or urlResolver
// Only store URLs if they are clickable and are configured using the Url
// property or provided by a custom URL resolver.
if (!isMvcUrl && node.Clickable)
{
url = this.siteMapChildStateFactory.CreateUrlKey(node);
// Check for duplicates (including matching or empty host names).
if (this.urlTable
.Where(k => string.Equals(k.Key.RootRelativeUrl, url.RootRelativeUrl, StringComparison.OrdinalIgnoreCase))
.Where(k => string.IsNullOrEmpty(k.Key.HostName) || string.IsNullOrEmpty(url.HostName) || string.Equals(k.Key.HostName, url.HostName, StringComparison.OrdinalIgnoreCase))
.Count() > 0)
{
var absoluteUrl = this.urlPath.ResolveUrl(node.UnresolvedUrl, string.IsNullOrEmpty(node.Protocol) ? Uri.UriSchemeHttp : node.Protocol, node.HostName);
throw new InvalidOperationException(string.Format(Resources.Messages.MultipleNodesWithIdenticalUrl, absoluteUrl));
}
}
// Add the URL
if (url != null)
{
this.urlTable[url] = node;
}
Finally no url is add to the urlTable, which result in FindSiteMapNode cannot find anything.
I am not sure if there needs to be specific configuration. Or should I implement custom XmlSiteMapProvider just add the url.
ISiteMapNodeProvider instances cannot use the FindSiteMapNode function for 2 reasons. The first you have already discovered is that finding by URL can only be done if you set the url attribute explicitly in the node configuration. The second reason is that the SiteMapBuilder doesn't add any of the nodes to the SiteMap until all of the ISiteMapNodeProvider instances have completed running, so it would be moot to add the URL to the URL table anyway.
It might help if you explain what you are trying to accomplish.
The ISiteMapNodeProvider classes have complete control over the data that is added to the SiteMapNode instances and they also have access to their parent SiteMapNode instance. This is generally all that is needed in order to populate the data. Looking up another SiteMapNode from the SiteMap object while populating the data is not supported. But as long as the node you are interested in is populated in the same ISiteMapNodeProvider instance, you can just get a reference to it later by storing it in a variable.
Update
Okay, I reread your question and your comment and it now just seems like you are looking in the wrong place. MvcSiteMapProvider v4 is no longer based on Microsoft's SiteMap provider model, so using XmlSiteMapProvider doesn't make sense, as it would sidestep the entire implementation. The only case where this might make sense is if you have a hybrid ASP.NET and ASP.NET MVC application that you want to keep a consitant menu structure between. See Upgrading from v3 to v4.
There are 2 stages to working with the data. The first stage (the ISiteMapBuilder and ISiteMapNodeProvider) loads the data from various sources (XML, .NET attributes, DynamicNodeProviders, and custom implementations of ISiteMapNodeProvider) and adds it to an object graph that starts at the SiteMap object. Much like Microsoft's model, this data is stored in a shared cache and only loaded when the cache expires. This is the stage you have been focusing on and it definitely doesn't make sense to lookup nodes here.
The second stage is when an individual request is made to access the data. This is where looking up data based on a URL might make sense, but there is already a built-in CurrentNode property that finds the node matching the current URL (or more likely the current route since we are dealing with MVC) which in most cases is the best approach to finding a node. Each node has a ParentNode and ChildNodes properties that can be used to walk up or down the tree from there.
In this second stage, you can access the SiteMap data at any point after the Application_Start event such as within a controller action, in one of the built in HTML helpers, an HTML helper template in the /Views/Shared/DisplayTemplates/ directory, or a custom HTML helper. This is the point in the application life cycle which you might call the lines SiteMaps.Current.FindSiteMapNode(rawUrl) or (more likely) SiteMaps.Current.CurrentNode to get an instance of the node so you can inspect its Attributes property (the custom attributes).
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
var currentNode = MvcSiteMapProvider.SiteMaps.Current.CurrentNode;
string permission = currentNode.Attributes.ContainsKey("permission") ? currentNode.Attributes["permission"].ToString() : string.Empty;
string programs = currentNode.Attributes.ContainsKey("programs") ? currentNode.Attributes["programs"].ToString() : string.Empty;
string agencies = currentNode.Attributes.ContainsKey("agencies") ? currentNode.Attributes["agencies"].ToString() : string.Empty;
// Do something with the custom attributes of the About page here
return View();
}
The most common usage of custom attributes is to use them from within a custom HTML helper template. Here is a custom version of the /Views/Shared/DisplayTemplates/SiteMapNodeModel.cshtml template that displays the custom attributes. Note that this template is called recursively by the Menu, SiteMapPath, and SiteMap HTML helpers. Have a look at this answer for more help if HTML helper customization is what you intend to do.
#model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModel
#using System.Web.Mvc.Html
#using MvcSiteMapProvider.Web.Html.Models
#if (Model.IsCurrentNode && Model.SourceMetadata["HtmlHelper"].ToString() != "MvcSiteMapProvider.Web.Html.MenuHelper") {
<text>#Model.Title</text>
} else if (Model.IsClickable) {
if (string.IsNullOrEmpty(Model.Description))
{
#Model.Title
}
else
{
#Model.Title
}
} else {
<text>#Model.Title</text>
}
#string permission = Model.Attributes.ContainsKey("permission") ? Model.Attributes["permission"].ToString() : string.Empty
#string programs = Model.Attributes.ContainsKey("programs") ? Model.Attributes["programs"].ToString() : string.Empty
#string agencies = Model.Attributes.ContainsKey("agencies") ? Model.Attributes["agencies"].ToString() : string.Empty
<div>#permission</div>
<div>#programs</div>
<div>#agencies</div>

How to discover all Entity Types? One of each?

I need to write a service that connects to CRM, and returns with a list of all of the entity available on the server (custom or otherwise).
How can I do this? To be clear, I am not looking to return all data for all entities. Just a list of every type, regardless of whether any actually exist.
You need to use RetrieveAllEntitiesRequest
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
// service is the IOrganizationService
RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)service.Execute(request);
foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
string logicalName = currentEntity.LogicalName;
// your logic here
}
note that you will get also system or hidden entities, like wizardpage or recordcountsnapshot
You will probably find these sections of the MSDN useful:
Customize Entity Metadata (lookout for the samples linked on that page).
Retrieve and Detect Changes to Metadata.

Unboundid LDAP domain attributes

I need to evaluate an user's password expiration time against an Active Directory.
I'm using Android and Unboundid sdk. I can successfully connect to server using this code
final SocketFactory _socket_factory;
final SSLUtil _ssl_util = new SSLUtil(new TrustAllTrustManager());
try {
_socket_factory = _ssl_util.createSSLSocketFactory();
}
catch (Exception e) {
Log.e(LOG_TAG, "*** Unable to initialize ssl", e);
return null;
}
LDAPConnectionOptions _ldap_connection_options = new LDAPConnectionOptions();
_ldap_connection_options.setAutoReconnect(true);
_ldap_connection_options.setConnectTimeoutMillis(30000);
_ldap_connection_options.setFollowReferrals(false);
_ldap_connection_options.setMaxMessageSize(1024*1024);
LDAPConnection _ldap_connection = new LDAPConnection(_socket_factory, _ldap_connection_options, _host, _port);
BindRequest _bind_request = new SimpleBindRequest(_username, _password);
BindResult _bind_result = _ldap_connection.bind(_bind_request);
I retreive user attributes using a search
Filter _filter = Filter.create("(userPrincipalName=lorenzoff)");
SearchRequest _search_request = new SearchRequest(_server._base_dn, SearchScope.SUB, _filter);
But how can I read the domain's attribute 'maxPwdAge'? I can see it in among the domain attributes...
I need it to evaluate the remaining days until user's password expires.
I had the same issue and found a solution. the idea is simple you have to access the base DN and get that attribute:
SearchRequest _search_request = new SearchRequest(_server._base_dn,
SearchScope.BASE, "(objectClass=*)","maxPwdAge");
with this you should get the result with that attribute, if you get SearchRequest.ALL_USER_ATTRIBUTES you will have all the attributes shown on your screenshot.
That attribute is common for all users, the next thing you need to do is to search your specific user as you where doing before an get the attribute pwdLastSet, as you would expect it has the timestamp of the last time the user changed his password.
now is simple, you need to find the expiration date with the last time the user change it, and the password age
hope it helps
If maxPwdAge is an "operational" attribute, it must be explicitly requested as part of your search request. "User" attributes are returned (as permissions permit), but "operational" attributes must be explicitly requested. To request maxPwdAge create your request as follows:
SearchRequest _search_request = new SearchRequest(_server._base_dn,
SearchScope.SUB, _filter,"maxPwdAge");
The SeachRequest constructor actually accepts a variable length list of attribute types also:
SearchRequest _search_request = new SearchRequest(_server._base_dn,
SearchScope.SUB,_filter,"maxPwdAge","minPwdAge",
SearchRequest.ALL_USER_ATTRIBUTES);
requests maxPwdAge, minPwdAge, and all other user attributes. To request all operational attributes, use SearchRequest.ALL_OPERATIONAL_ATTRIBUTES.

Sending ArrayCollections via P2P Flex

I have a question regarding P2P with flex.
When passing data between two applications using P2P. I get the following error:
warning: unable to bind to property 'piece' on class 'Object' (class is not an IEventDispatcher)
I've spent a few days using Google to try and find a solution, but a can't get rid of that error. I've tried using ObjectUtils, direct assignment, and creating a new ArrayCollection WITH the ObjectUtils inside the parenthesis and still can't solve the problem.
Purpose of code:
-> Two users connect via P2P
-> 1st user can manipulate pictures (stored as objects in the array collection).
-> 1st user sends updated ArrayCollection (with changed pictures) to 2nd user
-> 2nd user's ArrayCollection gets updated and now sees manipulated pics
As far as my knowledge of Flex goes (fairly new to it), I properly Binded what needed to be binded. Using pop-ups and trace, I was able to see that the data from the ArrayCollection gets copied in properly, but it just doesn't want to display.
Here are some snippets of my code:
[Bindable]
public var taken:ArrayCollection = new ArrayCollection ([
new picLayout(1,'sky.png'),
new picLayout(2,'bird.png')
])
public function receiveSomeData(pass:ArrayCollection):void
{
// Want to replace current version of variable "taken" with
// the one passed in using P2P
this.taken= new ArrayCollection(pass.source);
}
public function sendSomeData(free:ArrayCollection):void
{
sendStream.send("receiveSomeData",free);
}
<s:Button click="sendSomeData(taken)" label="Update" />
Thank You for your help and time!
I figured out what the problem was and how to fix it - with partial thanks to these pages:
Unable to Bind warning: class is not an IEventDispatcher
Flex Warning: Unable to bind to property 'foo' on class 'Object' (class is not an IEventDispatcher)
I knew that the information was being successfully sent to the other peer, but the problem was that the objects INSIDE the ArrayCollection weren't made bindable.
My solution to the problem was as follows:
Create a loop that sends each object in the ArrayCollection along with an index that tells you what value in the ArrayCollection you are streaming.
Now, since you are "streaming" the data, overwrite the current ArrayCollection, using the setItemAt() function with first field as "new ObjectProxy(passedObject)" and the second field as the passedIndex (Note): the ObjectProxy() function forces the passed object to be bindable.
Here is an updated snippet of my code:
[Bindable]
public var takenPics:ArrayCollection = new ArrayCollection ([
new picLayout(1,'sky.png'),
new picLayout(2,'bird.png')
])
private function sendSomeData(data:Object, index:int):void
{
sendStream.send("receiveSomeData",data,index);
}
private function receiveSomeData(passedPic:Object,ix:int):void
{
// ObjectProxy needed to force a bindable object
takenPics.setItemAt(new ObjectProxy(passedPic),ix);
}
public function sendPictures():void
{
// ix < 2 because size of ArrayCollection is 2
for (var ix:int = 0; ix<2; ix++)
sendSomeData(takenPics[ix],ix);
}

Resources