With the release of Baton in late 2022, ConductorOne shared its open-source vision for the future of identity management and access governance for the modern workforce. Baton, through the Baton SDK, provides a unified interface for modeling identity relationships in SaaS platforms. The Baton interface has been used in production to connect to and manage identity for services like Google Workspace, Amazon Web Services (AWS), 1Password, Slack, and dozens more.
Baton leverages the APIs made available by third-party applications to load the full state of an app’s users and their relationships to available app resources. For AWS, Baton can model how users relate to PermissionSets on accounts, whereas in GitHub, memberships to teams or repositories are represented. Baton connectors provide a comprehensive look at the internal state of an application to enable the access control and just-in-time (JIT) access features ConductorOne offers.
Introducing Baton feeds
While the information Baton aggregates is rich and highly adaptable, syncing all of it can take awhile, especially from larger services. That’s why we’re excited to introduce Baton feeds. Feeds was specifically built to add low-latency event streaming to Baton’s capabilities. Connectors employing feeds can now provide a quicker, more up-to-date view of an app’s internal state by reading directly from real-time data sources like the Okta System Log, Google Workspace OAuth logs, or Entra access logs. Adding feeds to any existing Baton connector using SDK v0.1.16 or newer is as easy as implementing a single function.
In this dev blog, I’ll break down how Baton feeds is designed to work as well as the new functionality it enables, including ConductorOne’s latest feature release—shadow app detection and monitoring.
Baton feeds interface and cursor
Baton feeds adds a new interface to the existing connector platform that lets you stream events in a flexible, unified way. All you have to do is implement one function and your connector is ready to start streaming events.
func (c *YourConnector) ListEvents(ctx context.Context, startAt *timestamppb.Timestamp, pToken *pagination.StreamToken) ([]*v2.Event, *pagination.StreamState, annotations.Annotations, error) {
// Implement YourConnector's event feed here
}
Our goal in building feeds was to provide the greatest opportunity for flexibility, so the core values considered in the design revolve around versatility. A feed keeps track of its state through StreamTokens and StreamStates. A StreamToken indicates the size (int) and cursor (string) needed by the connector to get the next page of data. The earliestEvent timestamp allows the connector to filter its results starting from a specified time. There’s no need for the connector to repeat events that occur before this timestamp. Once the connector gets a new page, it returns a StreamState that contains the cursor needed for the next page and a HasMore boolean indicating whether the connector should query for the next page of events immediately.
Cursors can often indicate much more information than just a page token to enable the greatest adaptability for each individual app. For example, the Google Workspace connector encodes both a next page token and the timestamp of the latest event processed by the connector for tracking its state. To demonstrate the flexibility this enables, let’s use the example of an API in which page 0 lists the latest events the service has available, and each page that follows lists older and older events. Many feed events are expected to report events and move forward through time. As long as we have a next page token, we want to make sure we keep loading all the historic data, otherwise we’re going to miss events.
The diagram below indicates how a Baton connector using this type of API would load data. We start querying from now and move backward through the pages of feeds. In the diagram, we see five pages worth of historical data. At the end of the fifth query, we have no more next page tokens and the connector returns HasMore = false, which indicates that we can move our earliestEvent up to the present and start querying all over again. The second part of the cursor, tracking the latest event, now indicates where we start querying from. Using this structure ensures we won’t miss any data and won’t query data we’ve already seen before.
Shadow apps detection powered by Baton feeds
Now let’s talk about Google Workspace (GWS) and Microsoft Entra. These platforms have become nearly ubiquitous identity providers (IdPs), used by many companies across the globe. Employees use these IdPs to sign into their company’s authorized apps, but they can also use them to log into apps their employer hasn’t yet sanctioned. Figma, Reddit, and Tailscale are just some of the many apps and services that support GWS and Entra as login providers. GWS and Entra don’t show the same activity for unauthorized— aka “shadow —apps that they do for those that have been authorized. As such, in the past, data from unauthorized apps wasn’t captured by connectors to be surfaced in ConductorOne.
However, GWS and Entra both provide audit trails that let users dive deeper into specific employee logins. But these audit trails are difficult and time-consuming to use as a way to track shadow app logins. For typical users, it’s nearly impossible to gain a comprehensive understanding of shadow app usage simply from the audit logs. Now, using Baton feeds, ConductorOne is able to ingest unauthorized login events to surface and provide a dashboard of employee logins to apps that aren’t currently managed within the platform. Users can see who has logged in and when the login took place as soon as those logins occur—no more chasing down logins in the audit log.
ConductorOne customers can now stream shadow app logins from their GWS and Entra environments. The platform shows discovered shadow apps along with the identities found within them. If users decide they want to bring a shadow app under management within ConductorOne, they can simply promote it to an authorized app and begin enforcing access controls and running access review campaigns, just as they would for any other app in their library. Shadow apps detection is only the first ConductorOne feature to launch that’s built on Baton feeds—we’re excited to continue exploring the capabilities feeds makes possible.
Event Types
The open-source baton-google-workspace connector already has support for Baton feeds’ UsageEvent objects. These UsageEvents describe individual logins from users to any potential application and are the main event type powering ConductorOne’s shadow apps feature. Feeds also supports GrantEvents and RevokeEvents, which will allow for low-latency monitoring of access changes in your connected integrations. Stay tuned for new features built on these event types.
To learn more about building your own connectors using the Baton SDK, check out our Baton docs or our repositories on GitHub. To see ConductorOne’s shadow apps detection and monitoring capabilities in action, book some time with our team!