Last time we looked at how Windows Azure Pack authenticates users in the Admin Portal. In this post we are going to look at how authentication works in the Tenant Portal.
Authentication in the Tenant Portal works exactly the same way authentication in the Admin Portal works.
Detailed and informative explanation, right?
Actually, with any luck you’ve read, and were more importantly, able to decipher my explanations in the last post. The reason for that is because we’re going to go a bit deeper into the configuration of how authentication is configured. If that’s actually the case then you know everything you need to know to continue on here. There are a couple minor differences between the Admin sites and Tenant sites, such as the tenant STS will store users in a standalone SQL database instead of Active Directory, and there is a set of public service endpoints that also federate with the Tenant STS. For the time being we can ignore the public API, but we may revisit it in the future.
One of the things this diagram doesn’t show is how the various services store configuration information. This is somewhat important because the Portals and APIs need to keep track of where the STS is, what is used to sign tokens, who is allowed to receive tokens, etc.
Since Windows Azure Pack is designed to be distributed in nature, it’s a fair bet most of the configuration is stored in databases. Let’s check the PowerShell cmdlets (horizontal spacing truncated a bit to fit):
PS C:\Windows\system32> Get-MgmtSvcDefaultDatabaseName
DefaultDatabaseName Description ——————- ———– Microsoft.MgmtSvc.Config Configuration store database Microsoft.MgmtSvc.PortalConfigStore Admin and Tenant sites database Microsoft.MgmtSvc.Store Rest API layer database Microsoft.MgmtSvc.MySQL MySQL resource provider database Microsoft.MgmtSvc.SQLServer SQLServer resource provider database Microsoft.MgmtSvc.Usage Usage service database Microsoft.MgmtSvc.WebAppGallery WebApp Gallery resource provider database
Well that’s handy. It even describes what each database does. Looking at the databases on the server we see each one:
Looking at the descriptions we can immediately ignore anything that is described as a “resource provider database” because resource providers in Windows Azure Pack are the services exposed by the Portals and APIs. That leaves us the Microsoft.MgmtSvc.Config,Microsoft.MgmtSvc.PortalConfigStore, Microsoft.MgmtSvc.Store, andMicrosoft.MgmtSvc.Usage databases.
The usage database looks like the odd one out so if we peek into the tables we see configuration information and data for usage of the resource providers. Scratch that.
We’re then left a Config database, a PortalConfigStore database, and a Store database. How’s that for useful naming conventions? Given the descriptions we could infer we likely only want to look into the PortalConfigStore database for the Tenant and Admin Portal configuration, and the Store database for the API configuration. To confirm that we could peek into the Config database and see what’s there. If we look in the Settings table we see a bunch of encrypted key value pairs. Nothing jumps out as being related to federation information like endpoints, claims, or signing certificates, but we do see pointers to database credentials.
If we quickly take a look at some of the web.config files in the various Windows Azure Pack sites we can see that some of them only have connection strings to the Configdatabase. Actually, if we look at any of the web.config files we’ll see they are protected, so we need to unprotect them:
PS C:\Windows\system32> Unprotect-MgmtSvcConfiguration -Namespace TenantAPI
Please remember to protect-* them when you’re done snooping!
If we compare the connection strings and information in the Config.Settings table, its reasonable to hypothesize that the Config database stores pointers to the other configuration databases, and the sites only need to have a configured connection string to a single database. This seems to only apply to some sites though. The Portal sites actually have connection strings only pointing to the PortalConfigStore database. That actually makes sense from a security perspective though.
Since the Portal sites are public-ish facing, they are more likely to be attacked, and therefore really shouldn’t have direct connections to databases storing sensitive information – hence the Web APIs. Looking at the architectural documentation on TechNet we can see its recommended that API services not be public facing (with the exception of the Public APIs) as well, so that supports my assertion.
Moving on, we now have the PortalConfigStore and the Store databases left. The descriptions tell us everything we need to know about them. We end up with a service relationship along the lines of:
Okay, now that we have a rough idea of how configuration data is stored we can peek into the databases and see what’s what.
Portal Sites Authentication
Starting with the PortalConfigStore database we see a collection of tables.
The two tables that pop out are the Settings table and the aspnet_Users table. We know the Auth Site for the tenants stores users in a database, and lookie here we have a collection of users.
Next up is the Settings table. It’s a namespace-key-value-pair mapped table. Since this database stores information for multiple sites, it makes sense to separate configuration data into multiple realms – the namespaces.
There are 4 namespaces we care about:
- AdminSite
- AuthSite
- TenantSite
- WindowsAuthSite
Looking at the TenantSite configuration we see a few entries with JSON values:
- Authentication.IdentityProvider
- Authentication.RelyingParty
Aha! Here’s where we store the necessary bits to do the federation dance. TheAuthentication.RelyingParty entry stores the information describing the TenantSite. So when it goes to the IdP with a request it can use these values. In my case I’ve got the following:
{ "EncryptionCertificate":null, "Realm":"https://azureservices/TenantSite", "ReplyTo":https://manage-cloud.syfuhs.net/ }
Really, just the bare minimum to describe the RP. The Realm, which is the unique identifier of the site, the Reply To URL which is where the token should be returned to, and the Encryption Certificate in case the returned token is encrypted – which it isn’t by default. With this information we can make a request to the IdP, but of course, we don’t know anything about the IdP yet so we need to look up that configuration information.
Looking at the Authentication.IdentityProvider entry we see everything else we need to complete a WS-Federation passive request for token. This is my configuration:
{ "Realm":"https://azureservices/AuthSite", "Endpoint":"https://auth-cloud.syfuhs.net/wsfederation/issue", "Certificates":[ "MIIC2...ADLt0=" ] }
To complete the request we actually only need the Endpoint as that describes where the request should be sent, but we also now have the information to validate the token response. The Realm describes who minted the token, and the Certificates element is a collection of certificates that could have been used to sign the token. If the token was signed by one of these certificates, we know it’s a valid token.
We do have to go one step further when validating this though, as we need to make sure the token is intended to be used by the Tenant Portal. This is done by comparing the audience URI in the token (see the last post) to the Realm in theAuthentication.RelyingParty configuration value. If everything matches up we’re good to go.
We can see the configuration in the AdminSite namespace is similar too.
Next up we want to look at the AuthSite namespace configuration. There are similar entries to the TenantSite, but they serve slightly different purposes.
The Authentication.IdentityProvider entry matches the entry for the TenantSite. I’m not entirely sure of its purpose, but I suspect it might be a reference value for when changes are made and the original configuration is needed. Just a guess on that though.
Moving on we have the Authentication.RelyingParty.Primary entry. This value describes who can request a token, which in our case is the TenantSite. My entry looks like this:
{ "EncryptionCertificate":null, "Realm":"https://azureservices/TenantSite", "ReplyTo":https://manage-cloud.syfuhs.net/ }
It’s pretty similar to the configuration in the TenantSite entry. The Realm is the identifier of which site can request a token, and the Reply To URL is where the token should be returned once its minted.
Compare that to the values in the WindowsAuthSite namespace and things look pretty similar too.
So with all that information we’ve figured out how the Portal sites and the Auth sites are configured. Of course, we haven’t looked at the APIs yet.
API Authentication
If you recall from the last post the API calls are authenticated by attaching a JWT to the request header. The JWT has to validated by the APIs the same way the Portals have to validate the JWTs received from the STS. If we look at the diagram above though, the API sites don’t have access to the PortalConfigStore database; they have access to the Storedatabase. Therefore its reasonable to assume the Store database has a copy of the federation configuration data as well.
Looking at the Settings table we can confirm that assumption. It’s got the same schema as the Settings table in the PortalConfigStore database, though in this case there are different namespaces. There are two namespaces that are of interest here:
- AdminAPI
- TenantAPI
This aligns with the service diagram above. We should only have settings for the namespaces of services that actually touch the database.
If we look at the TenantAPI elements we have four entries:
- Authentication.IdentityProvider.Primary
- Authentication.IdentityProvider.Secondary
- Authentication.RelyingParty.Primary
- Authentication.RelyingParty.Secondary
The Authentication.IdentityServer.Primary entry matches up with the TenantSite Authentication.IdentityServer entry in the PortalConfigStore database. That makes sense since it needs to trust the token same as the Tenant Portal site. The Secondary element is curious though. It’s configured as a relying party to the Admin STS. I suspect that is there because the Tenant APIs can be called from the Admin Portal.
Comparing these values to the AdminAPI namespace we see that there are only configuration entries for the Admin STS. Seems reasonable since the Tenant Portal probably shouldn’t be calling into admin APIs. Haven’t got a clue why the AdminAPI relying party is configured as Secondary though . Artifact of the design I guess. Another interesting artifact of this configuration is that the ReplyTo values in the RelyingPartyentries show the default value from when I first installed the services. We see something like:
{ "EncryptionCertificate":null, "Realm":"https://azureservices/TenantSite", "ReplyTo":https://syfuhs-cloud:30081/ }
And
{ "EncryptionCertificate":null, "Realm":"https://azureservices/AdminSite", "ReplyTo":https://syfuhs-cloud:30091/ }
I reconfigured the endpoints to be publically accessible so these values are now incorrect.
API’s can’t really use Reply To the same passive requests can, so it makes sense that they don’t get updated – they don’t have to be updated. The values don’t have to be present either, but again, artifacts I guess.
Conclusion
In the previous post we looked at how authentication works conceptually, and in this post we looked at how authentication is configured in detail. Next time we’ll take a look at how we can reconfigure Windows Azure Pack to work with our own IdPs.
No spoilers this time.