Latest Entries »

Scrap my last post… Today I found I could no longer login to sharepoint and other federated services were acting strangely. I tried to troubleshoot but ultimately gave up.

Finally came the time to see if my weekly VM backups (and nightly incrementals) were actually any good… 15 minutes later and everything’s back to how it was 2 night’s ago!

Screen Shot 2015-04-21 at 15.48.06

Thankfully Veeam worked a treat and ADFS was back working perfectly BUT we still have our expiring SSL warning.

Screen Shot 2015-04-21 at 21.00.32

My theory as to what went wrong before… Whilst I had updated my SSL certificates on my on-premise ADFS server (including the token signing certificate), I think the Office365 hosted servers also need this same matching certificate. So, let’s try a different approach.

This time I followed a different link http://www.kraak.com/?p=190. I started the same way as before, replacing the SSL certificate in IIS. However, I didn’t update the token-signing or token-decrypting certificates in ADFS. Instead I issued the following commands;

Connect-MsolService
Get-MsolFederationProperty -DomainName tickett.net

At this stage, I can essentially see that both the ADFS Server (on-premise) and Microsoft Office 365 (hosted) certificates match;

Screen Shot 2015-04-21 at 21.16.46

At this point I noticed that, not only did they (obviously) bare the old dates, but they also bare the internal server name (and not the FQDN of either my old or new SSL certificates for IIS). This further backs up my theory that using the same certificate for IIS and ADFS yesterday was wrong. And in fact, it appears ADFS generates it’s own certificates when instructed to do so;

Update-ADFSCertificate -CertificateType: Token-Signing -Urgent:$true
Get-MsolFederationProperty -DomainName tickett.net

Screen Shot 2015-04-21 at 21.24.05

Right, we’re part way there. The ADFS Server certificate has now been renewed, but the Microsoft Office 365 certificate now needs to be updated;

Update-MsolFederatedDomain -DomainName tickett.net
Get-MsolFederationProperty -DomainName tickett.net

Bingo, now they both match! Exactly the same sequence of commands now needs to be executed for the token-decrypting certificate;

Update-ADFSCertificate -CertificateType: Token-Decrypting -Urgent:$true
Update-MsolFederatedDomain -DomainName tickett.net

And voila! I can now login perfectly to all my federated/SSO application/sites and Office365 webmail no longer warns me about a certificate approaching expiry.

*EDIT* This turned out to fail, please read the follow-up post; https://tickett.wordpress.com/2015/04/21/second-attempt-updating-adfs-ssl-certificate-on-windows-server-2012-r2/ 

I noticed a warning in Office 365 webmail that my SSL certificate was due to expire soon and hoped updating it would be a trivial task.

As always, I used https://www.startssl.com/ to generate a new certificate. I fired up IIS on the ADFS server and imported the new certificate (Server Certificates, Import). When I tried to bind the certificate to the ADFS https site I received a warning/error about a missing intermediate CA certificate. This was easily fixed by downloading the “Class 2 Intermediate Server CA” certificate from StartSSL and importing into the windows certificate store under Intermediate Certificate Authorities (Launched from the start menu by searching for “Manage computer certificates”);

Screen Shot 2015-04-20 at 17.07.17

Binding to the site in IIS was now successful. However, none of my federated applications were working. Just an ADFS error;

Screen Shot 2015-04-20 at 17.14.57

And some errors to match in the event log;

Screen Shot 2015-04-20 at 17.17.14

On each login attempted I was received the following 3 events;

Event: 111

The Federation Service encountered an error while processing the WS-Trust request.
Request type: http://schemas.microsoft.com/idfx/requesttype/issue

Additional Data
Exception details:
System.ArgumentNullException: Value cannot be null.
Parameter name: certificate
at Microsoft.IdentityModel.Threading.AsyncResult.End(IAsyncResult result)
at Microsoft.IdentityModel.Threading.TypedAsyncResult`1.End(IAsyncResult result)
at Microsoft.IdentityModel.SecurityTokenService.SecurityTokenService.EndIssue(IAsyncResult result)
at Microsoft.IdentityServer.Web.WSTrust.SecurityTokenServiceManager.Issue(RequestSecurityToken request, IList`1& identityClaimSet)

Event: 1000

An error occurred during processing of a token request. The data in this event may have the identity of the caller (application) that made this request. The data includes an Activity ID that you can cross-reference to error or warning events to help diagnose the problem that caused this error.

Additional Data

Caller:
TICKETT\lee

OnBehalfOf user:

ActAs user:

Target Relying Party:
http://adfs.tickett.net/adfs/services/trust

Device identity:

User action:
Use the Activity ID data in this message to search and correlate the data to events in the Event log using Event Viewer. This Activity ID will also be shown as additional information in the error page when an error occurs in the federation passive Web application.

Event: 364

Encountered error during federation passive request.

Additional Data

Protocol Name:
wsfed

Relying Party:
urn:federation:MicrosoftOnline

Exception details:
Microsoft.IdentityServer.RequestFailedException: MSIS7012: An error occurred while processing the request. Contact your administrator for details. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: certificate
at Microsoft.IdentityModel.Threading.AsyncResult.End(IAsyncResult result)
at Microsoft.IdentityModel.Threading.TypedAsyncResult`1.End(IAsyncResult result)
at Microsoft.IdentityModel.SecurityTokenService.SecurityTokenService.EndIssue(IAsyncResult result)
at Microsoft.IdentityServer.Web.WSTrust.SecurityTokenServiceManager.Issue(RequestSecurityToken request, IList`1& identityClaimSet)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.SubmitRequest(MSISRequestSecurityToken request, IList`1& identityClaimCollection)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.RequestBearerToken(MSISRequestSecurityToken signInRequest, Uri& replyTo, IList`1& identityClaimCollection)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.RequestSingleSingOnToken(ProtocolContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSsoSecurityToken(WSFederationSignInContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken, SecurityToken& ssoSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSignInResponseCoreWithSecurityToken(WSFederationSignInContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSignInResponse(WSFederationSignInContext federationPassiveContext, SecurityToken securityToken, SecurityToken deviceSecurityToken)
--- End of inner exception stack trace ---
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSignInResponse(WSFederationSignInContext federationPassiveContext, SecurityToken securityToken, SecurityToken deviceSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.ProcessProtocolRequest(ProtocolContext protocolContext, PassiveProtocolHandler protocolHandler)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)

System.ArgumentNullException: Value cannot be null.
Parameter name: certificate
at Microsoft.IdentityModel.Threading.AsyncResult.End(IAsyncResult result)
at Microsoft.IdentityModel.Threading.TypedAsyncResult`1.End(IAsyncResult result)
at Microsoft.IdentityModel.SecurityTokenService.SecurityTokenService.EndIssue(IAsyncResult result)
at Microsoft.IdentityServer.Web.WSTrust.SecurityTokenServiceManager.Issue(RequestSecurityToken request, IList`1& identityClaimSet)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.SubmitRequest(MSISRequestSecurityToken request, IList`1& identityClaimCollection)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.RequestBearerToken(MSISRequestSecurityToken signInRequest, Uri& replyTo, IList`1& identityClaimCollection)
at Microsoft.IdentityServer.Web.Protocols.PassiveProtocolHandler.RequestSingleSingOnToken(ProtocolContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSsoSecurityToken(WSFederationSignInContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken, SecurityToken& ssoSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSignInResponseCoreWithSecurityToken(WSFederationSignInContext context, SecurityToken securityToken, SecurityToken deviceSecurityToken)
at Microsoft.IdentityServer.Web.Protocols.WSFederation.WSFederationProtocolHandler.BuildSignInResponse(WSFederationSignInContext federationPassiveContext, SecurityToken securityToken, SecurityToken deviceSecurityToken)

The earlier Office365 warning did link to a page which also included instructions for updating the certificates within ADFS, so I went ahead and did that too (In ADFS Manager, Set Service Communications Certificate, Add Token-Signing Certificate and Add Token-Decrypting Certificate). But still nothing… restarting didn’t help either.

Eventually I found an article with a few powershell commands; http://blogs.technet.com/b/tune_in_to_windows_intune/archive/2013/11/13/replace-certificates-on-adfs-3-0.aspx

Get-AdfsSslCertificate

Screen Shot 2015-04-20 at 17.24.02

Comparing this to the new certificate, I can see that it doesn’t match;

Screen Shot 2015-04-20 at 17.25.20

Set-AdfsSslCertificate -Thumbprint NEWSSLCERTIFICATETHUMBPRINT

Screen Shot 2015-04-20 at 17.26.18

Despite returning an error message referencing the old SSL certificate, you can see that the new one is now correctly assigned (by issuing the Get-AdfsSslCertificate command again).

And voila, I can now log in to my federated applications.

*EDIT* This turned out to fail, please read the follow-up post; https://tickett.wordpress.com/2015/04/21/second-attempt-updating-adfs-ssl-certificate-on-windows-server-2012-r2/ 

Kicking back for a week at Center Parcs. Came fully prepared with Raspberry Pi & 2TB Portable Hard Drive fully loaded but forgot the damn remote! My HTC One has an IR remote built in, but the Microsoft MCE remote isn’t listed. Every result googled turned up was an XBMC or Media Center remote which only works over the network/LAN.

Eventually, after trying a dozen or so IR apps with no luck, we found ZappIR.

zappir

After trying a few combinations- Console/Media Manager -> Microsoft -> Media Manager MCE Media Center Code Group 2- Bingo!

Now back to kicking back! Nice little hot tub, steam room and sauna in the back garden!

11042999_10155192464790567_1824434695954957278_n

I’ve seen a number of projects posted using the Amazon Kindle as a “standalone” wireless display and decided it was time to join the party. I picked up a secondhand kindle from eBay for £20 and got cracking.

First step was rooting/jailbreaking the kindle. Pretty easy using the instructions from http://www.mobileread.com/forums/showthread.php?t=88004

I then enabled SSH over WiFi so I didn’t have to mess around booting into diagnostics mode and plugging in to USB every time I wanted to make changes.

Lees-Air:~ leetickett$ ssh root@192.168.0.229

Welcome to Kindle!

#################################################
#  N O T I C E  *  N O T I C E  *  N O T I C E  # 
#################################################
Rootfs is mounted read-only. Invoke mntroot rw to
switch back to a writable rootfs.
#################################################
[root@kindle root]#

The most helpful project to get me started was https://github.com/antimega/kindleframe it uses PhantomJS and pngcrush on a linux server to prepare the image. Handily I already have a Centos server I could easily use for this. I tweaked Chris’ script a little- starting with the shell script called by cron;

#!/bin/sh
cd /var/www/html
phantomjs update.js
convert morning.png -resize 80% screenshot.png
convert morning.png -rotate 90 screenshot.png
pngcrush -c 0 -nofilecheck screenshot.png screenshot_crush.png

Then update.js. I had to tackle a few issues;

  • Cycling between different pages (achieved by dividing the current minute by 5 and choosing a URL based on the remainder)
  • My SSRS report takes 15 seconds to run (using setTimeout(takeScreenShot, 20000); ensures the report has loaded before the screenshot is taken)
  • My SSRS report requires authentication (simply adding page.settings.userName = ‘x’; and page.settings.password = ‘y’;)
var page = require('webpage').create();
var d = new Date();
var n = d.getMinutes();
var url = '';
var px_top = 120;
var px_left = 10;
if (n%5==0)
{
 url = 'http://pvoutput.org/intraday.jsp?id=26603&sid=24317';
}
else if (n%5==2)
{
 url = 'http://pvoutput.org/list.jsp?id=26603&sid=24317';
}
else
{
 url = 'http://192.168.0.188/ReportServer/Pages/ReportViewer.aspx?%2fTEL+Wall+Thing%2fWallDash&rs:Command=Render';
 page.viewportSize = {
  width: 1920,
  height: 1080
 };
 page.settings.userName = 'xxx';
 page.settings.password = 'yyy';
 px_top = 45;
 px_left = 470;
}
page.open(url, function () {
	page.clipRect = { top: px_top, left: px_left, width: 1000, height: 750 }; 
	page.evaluate(function() {
    	document.body.bgColor = 'white';
	});
        var elapsed = 0;
	setTimeout(takeScreenShot, 20000);
	function takeScreenShot() {
            	page.render('screenshot.png');
            	phantom.exit();
    	}
});

Then added the script to cron to run every minute and voila.

Once SSH’ed onto the kindle you’ll need to;

mntroot rw

Then proceed to create the script to grab the image and display it (I also added a few lines to display the battery %age in the bottom corner);

#!/bin/sh
cd /var/tmp/root
rm screenshot_crush.png
eips -c
eips -c
wget http://user:pass@tickett.dyndns.com:777/html/screenshot_crush.png
eips -g screenshot_crush.png
local batt=$(cat /sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity)
batt=${batt%%\%*}
eips 1 39 "$batt"

I’ve setup port forwarding on my firewall to allow traffic through on an obscure port, added a .htpasswd and you’ll notice i’m using an external domain name in my script (i’ve substituted something fictitious)- this allows me to use the display anywhere with an internet connection (literally anywhere as I can tether to my mobile phone).

And here it is;

IMAG1435

IMAG1433

IMAG1432

Here’s how the SSRS report looks in it’s full glory (you can see the area i’ve chosen to display on the kindle);

wall_dash

I’ve chosen not to kill powerd and framework for now, so the kindle will still go to sleep. The next step- if I ever get round to it, will be trying to save power by sleeping or disabling WiFi between updates. I’ve found a little bit of information on how this might be possible (http://www.mobileread.com/forums/showthread.php?t=221497) but still some way off.

I will no doubt add some additional screens (weather forecast, router traffic, network monitoring etc), and it would be nice to have a way of scrolling between images using one of the kindle keys.

Wouldn’t it be great if you could buy something like this off the shelf? Why should we have to hack an existing device? I stumbled across an interesting kickstarter campaign doing exactly this, unfortunately it’s a tiny 2″ screen (https://www.kickstarter.com/projects/914874115/displio-wifi-display-that-tracks-whats-important-t)- maybe one day!

I’m also in the market for a bigger device (i’d love to replace the 21″ monitor which sits on my wall) but for a portable option 9″ or 10″ would probably suffice. A real shame the Kindle DX was discontinued, that would have been perfect (although could do with losing the keyboard). Also looks like a few similar devices; Asus eeeReader DR900, Onyx BOOX M96 (they seem quite expensive and I haven’t looked into whether they have been (or even need to be) rooted, or how easily something similar could be achieved on Android).

Other similar projects worth a look;

http://www.shatteredhaven.com/2012/11/1347365-kindle-weather-display.html
https://randomcoderdude.wordpress.com/2015/01/31/using-the-kindle-as-an-information-display
https://github.com/ufuchs/weather-on-kindle4nt
http://hackaday.com/2015/02/16/wi-fi-connected-e-ink-display/

Further to https://tickett.wordpress.com/2014/12/04/doh-it-doesnt-fit/

I was unable to find a replacement heatsink which would allow the Broadcom NIC to fit. I did however manage to replace the standard heatsink screws with these (12mm M3). I bought a pack of 100 from RS for a mere £1.52 (rs stock no 553-403);

IMAG1252

You can see how much smaller they are than the stock screws;

IMAG1253

Here it is fitted;

IMAG1259

And the card fit;

IMAG1261

Note that I added a bit of electrical tape to the end of the NIC to make 100% sure none of the components will short. As well as slotting a small sheet of paper between the card and the motherboard.

Further to a post over 3 years ago https://tickett.wordpress.com/2011/09/27/updateable-excel-frontend-for-sql-view/ – I have finally given up the search for a ready made solution and built something myself.

I work with a number of systems which have functionality gaps and/or need a simpler (quicker) interface for data entry. The solution is essentially a SQL view (or stored procedure) with a simple grid (excel like) front-end. If any data needs to be captured not currently handled by the system a custom table is created to hold the fields.

My previous Excel based solution works rather well, but is starting to show it’s age. I am now beta testing a web based solution i have built;

Screen Shot 2014-12-11 at 20.34.43

The application is extremely simple to configure- enter the SQL to retrieve & update the data;

Screen Shot 2014-12-11 at 20.43.43

And list the columns with some attributes (ReadOnly, Hidden, Title, Width etc);

Screen Shot 2014-12-11 at 20.42.10

And you’re all set!

Functionality currently includes;

  • Easy configuration
  • Simple/fast data entry (with validation)
  • Column resizing (non-persistent)
  • Sort on any column

Next steps;

  • Test (find and fix bugs)
  • Optimise code
  • Allow parameters in select SQL

That’s better!

After discovering last night that my newly acquired Broadcom 57810A Dual Port 10Gb PCIE Copper (RJ45) Ethernet NICs didn’t fit my Supermicro AS-2022TG-HIBQRF, I was pleased to find they do fit my Supermicro AS-1042G-LTF.

And best of all, absolutely no setup/configuration was necessary. I simply powered down the host, replaced the NIC and powered back up. The ports automatically assigned the same as the NIC I removed.

Screen Shot 2014-12-05 at 09.08.19

Doh! It doesn’t fit!

Looking for a cheaper alternative to the Intel X540-T2 (Dual Port 10Gb PCIE Copper (RJ45) Ethernet NIC) I purchased a Broadcom 57810A (Dual Port 10Gb PCIE Copper (RJ45) Ethernet NIC).

I eagerly opened up my server (Supermicro AS-2022TG-HIBQRF) but it doesn’t quite fit!

Screen Shot 2014-12-04 at 22.14.11

You can see the plastic RAM shroud just touching, and the CPU heatsink just touching but unfortunately the problem is the heatsink screw (just below the back end of the card);

Screen Shot 2014-12-04 at 22.14.36

Very frustrating! If the screw lay where the 20 pin connector / holes were i’d consider getting out the dremel. You can clearly see some chips where i’d need to cut though!

I have had a look and can’t find any alternative heatsinks that might free up the space either!

Guess i’ll have to stick with the Intel X540-T2 for now (admittedly I don’t even know if the Broadcom 57810A is compatible with the server & ESX yet… although I will be sure to try it in my Supermicro AS-1042G-LTF later (watch this space).

Here’s the X540-T2;

Screen Shot 2014-12-04 at 22.23.05

I have just setup an SSRS report for my helpdesk to show open calls, unread e-mails, some KPIs and graphs. I bought a cheap monitor, wall mounted and attached a raspberry pi.

I started with the latest Raspbian image and spent some time tweaking it to boot into x and launch chromium with the homepage set to the URL of my report. Unfortunately it was pretty flakey and always prompted for username/password so I had to VNC in every morning to authenticate.

Yesterday morning chromium decided it no longer wanted to load the report. I tried running;

sudo apt-get update
sudo apt-get upgrade
sudo raspi-update

And rebooted… Or at least I tried to but it would no longer boot- hanging on a message along the lines of;

mmcblk0: error -110

Rather than start again from scratch I decided someone else must have already tackled this “kiosk” style scenario and went on the hunt. Enter Raspberry Webkiosk; http://www.binaryemotions.com/raspberry-webkiosk/ (after a quick trial I paid the €9.90 “donation” to get the full version).

The image took care of the operating system, booting straight into full screen chromium with the home page set to the report URL but I was still stuck with the authentication prompt.

I hoped I could simply enable Anonymous Authentication in IIS, but the report server virtual directories don’t appear in IIS and the information available online all suggests this can’t be done.

The next idea was to try and configure chromium to remember the login credentials. Whilst I was able to save the username and password the prompt still persisted.

Final idea was to try and use an asp/html script of some sort. I then remembered a site I stumbled across recently with some sample/demo reports; http://www.reportsurfer.com/ which didn’t require authentication. I took a look at the html source and could see some simple javascript being used to pass the credentials.

So I built a simple “proxy” page in the default IIS site to redirect to the SSRS report and pass the username & password (the script must be on the same hostname/port to work).

<html>
  <head>
   <script>
var _0x1751=["\x61\x66","\x76\x76"];

function getHTTPObject() {
    if (typeof XMLHttpRequest != 'undefined') {
        return new XMLHttpRequest();
    }
    try {
        return new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
        try {
            return new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
    }
    return false;
}	

function runReport() {
  var http = getHTTPObject();
  var url= "http://rs-01/ReportServer/Pages/ReportViewer.aspx?%2fTEL+Wall+Thing%2fWallDash&rs:Command=Render";
  http.onreadystatechange = function() {
    if (http.readyState == 4) {
      if (http.status == 401) {
        runReport(); 
      }
      if (http.status == 200) {
        document.location = url;
      }
    }
  };
  http.open("get", url, true, _0x1751[0x0], _0x1751[0x1]);
  http.send(null);
  return false;
}
    </script>
  </head>
  <body onload="runReport();">
  </body>
</html>

To use the script yourself, you essentially need to amend the top line;

var _0x1751=["\x61\x66","\x76\x76"];

The first value is the username and the second value is the password (hex encoded just to add some really basic obfuscation). Obviously this is easily reversible so you should create a new account with only permission for the specific report(s) they should be able to access. You can use http://string-functions.com/string-hex.aspx to convert your login details to hex.

Then simply update the report URL;

var url= "http://rs-01/ReportServer/Pages/ReportViewer.aspx?%2fTEL+Wall+Thing%2fWallDash&rs:Command=Render";

And you’re all set!

helpdesk

Follow

Get every new post delivered to your Inbox.

Join 2,277 other followers

%d bloggers like this: