start docker as systemd on centos7/rhel7

Here is an example how you can start a docker container as a service. After reboot this docker instance will be started.
Create a service file like this: 

[Unit]

Description=Redis Docker Container 

After=docker.service

Requires=docker.service

 

[Service]

User=chris

RemainAfterExit=true

ExecStart=/bin/docker run -d –name redis redis

ExecStop=/bin/docker stop -t 2 redis 

ExecStopPost=/bin/docker rm -f redis

 

[Install]

WantedBy=multi-user.target

/etc/systemd/system/redis.service

test it with the following command:

systemctl start redis

stop it with: systemctl stop redis

make this permanent with systemctl enable redis

Config Azure AD authentication on tomcat

Just made a simple demo project (not for production purposes) that shows you how you can use the Azure Active Directory as a REALM for your authentication. Nowadays you would use a framework that does 3rd party authentication for you…your custom authenticator will use a third party framework that federates the authentication to a (trusted) 3rd party like Facebook or Google.

Please note that this is NOT the way to use AAD in a production environment.
This is Demo code to show how you can (mis)use AAD as a LDAP solution.
In future I will create a federated authentication solution using AAD.

Here is the project: https://github.com/cvugrinec/microsoft/tree/master/java-webapp-tomcat-aad

Here you see the code in action: https://youtu.be/i61I3muADDA

Docker Image for Azure CLI and Azure Powershell

If you are a MAC or Linux user like I am and you like to manage your azure environment with azure-cli or azure-powershell you can use the following docker Image: cvugrinec/ubuntu-azure-powershellandcli:latest

Just type the following:

docker run –it  cvugrinec/ubuntu-azure-powershellandcli /bin/sh

Please note that for azure-powershell only ARM mode is supported. Azure cli supports ASM and ARM mode.

70-533 Azure certification notes

Recently I certified myself for the 70-533 exam, which  is the MCP certification for Implementing Microsoft Azure infrastructure solutions. Here are my notes what I think you should do (HANDS ON) in order to pass:

  • Web Applications/ Paas services
    • Deploy some webapplications, using the concept of slots. Also pretend to do a production update
    • Enable monitoring for 1 or 2 endpoints in your app for different test locations
    • Play with the traffic manager and understand when to use it
    • Enable CDN and understand what needs to be done (for e.g. which DNS records)
    • Implement several databases and understand the difference in products and service levels.
    • Implement autoscaling
  • Azure Virtual Machines
    • Create some VMS’ preferable with own image and attaching own datadisks
    • Make an availabilty plan
    • Make a scaleset
    • Do an update on a update domain
    • Test a failover scenario with the failover domain(s)
    • Enable diagnostics and download the diagnostics with powershell commands
  • Storage and Disks
    • Create storage accounts with powershell, create shares on it and put files on them
    • Upload a VHD and create a image for an OS you would like to make available
    • Create a datadisk and play with the optimization parameters for caching
    • Play with Azure Site Recovery and Backup manager
    • Play and understand the with several zones (LRS/ZRS/GRS/GRS(A))
  • Azure Virtual Networks
    • Play with the setting for Site to Site and Point to Site and understand when to use Express route. Understand when a VPN needs to be installe
    • Export an existing network config, change it and import it back again
    • Make a connection between 2 Virtual Networks
    • Implement subnets and routing between them
    • Implement NSG and play with ACL
    • Play with Static IP addresses for PAAS services (reserved) or VM’s
  • Azure Active Directory (IAM)
    • Add a custom domain to your AAD
    • Add a custom web application and use the SSO with own credential store
    • Add an application from the store and enable SSO
    • Add an application using existing SSO (for e.g. from Google or facebook)
    • Implement a multisite network

To be honest I haven’t done all of this…but this is what I think I should have done in retrospective. The exam is doable ( I passed it the first time…so everyone can 🙂  If I would create a course for passing this exam (maybe I will someday) than I would spend a week doing the stuff I mentioned here. PS: I passed my exam by doing prep exams from: http://mindhub.com …

Managing your gmail mailbox

I found out a way to get full control of my heavily loaded gmail mailbox… just plain code…without complicated looking (not easy to find) user menu’s to configure settings for archiving and cleaning my mailbox. Login to your gmail account (with your browser)…and then go to https://script.google.com/

Here you can put your (javascript) code and even debug it. Even better…after you are finished, you can expose this code as a (web)service or schedule it with the built in timer, woa …excellent dude!!!

Here is a snippet of the code I am using:

[javascript]

function cleanUp() {
var delayDays = 0; // Enter # of days before messages are moved to trash
var maxDate = new Date();
cleanupCandidates = ["meetup.com","alison.com","voordeelvanger.nl","email.campaign@sg.booking.com","alibaba@email.alibaba.com","linkedin.com","ezine.ns.nl","tix.nl","gorillasports.nl","tommyteleshopping.com","poldercasino.com","hortonworks.com","connect.wso2.com","implicit-explicit.com","geocaching.com","autodna.mail"];

maxDate.setDate(maxDate.getDate()-delayDays);
gthreads = GmailApp.getInboxThreads();
for (var fc=0; fc<cleanupCandidates.length; fc++){
for (var i=0; i<gthreads.length; i++){
messages = gthreads[i].getMessages();
for (var j=0; j<messages.length; j++){
if(messages[j].getFrom().indexOf(cleanupCandidates[fc])>-1){
if (messages[j].getDate()<=maxDate){
Logger.log("Message older than maxdate ("+delayDays+"days)…removing it: ");
Logger.log("THREAD ID"+gthreads[i].getId()+" FROM: "+messages[j].getFrom()+" subject: "+messages[j].getSubject());
messages[j].moveToTrash();
}
}
}
}
}
}

function labelStuff(){
archiveCandidates = ["slack.com","googleplay-noreply@google.com","microsoft.com","klm-mail.com","redhat.com","transip.nl","eve-dev1.datalinks.nl","eve-dev.datalinks.nl","bonque.nl","itaq.nl","email.apple.com","Niels Westmeijer <niels@eve.nu>"];
labelCandidate = ["Archief/eve","Archief/playstore","Archief/microsoft","Archief/reizen","Archief/redhat","Archief/hosting","Archief/hosting-sec","Archief/hosting-sec","Archief","Archief","Archief/iTunes","Archief/eve"];

gthreads = GmailApp.getInboxThreads();
for (var i=0; i<gthreads.length; i++){
messages = gthreads[i].getMessages();
if(messages.length!=null){
for (var j=0; j<messages.length; j++){
fromMail=messages[j].getFrom();
Logger.log("Evaluating message frpm: "+fromMail);
foundAtLocation=archiveCandidates.indexOf(fromMail);
if(foundAtLocation>0){
label=labelCandidate[foundAtLocation];
from=archiveCandidates[foundAtLocation];
Logger.log("Found at:"+foundAtLocation+" Applying label "+label+" for: THREAD ID"+gthreads[i].getId()+" FROM: "+from+" subject: "+messages[j].getSubject());
eveLabel = GmailApp.createLabel(label);
gthreads[i].addLabel(eveLabel);
gthreads[i].moveToArchive();

}
}
}
}
}
[/javascript]

here a screeshot:

Schermafbeelding 2016 02 15 om 21 52 35

screenshot of the trigger/ scheduler…cronjob editor

screeshot_trigger

picketlink implementation notes for websphere

Schermafbeelding 2016 01 28 om 08 44 08


Flow in a nutshell

User acces the application

  • The default deployment descriptor will state that this is a protected resource and needs to be handled by its container
  • The application does its security stuff within the context of websphere security domain, within this domain it is configured to make access to this application only available via a TAI (Trusted Authentication Interceptor)
  • The TAI is configured that authentication errors (which is the case if you access the application the 1st time) should be redirected to the IDP, the TAI makes sure that an authentication (LTPA) cookie is also set:
  • We have configured a SP which an SAML authentication request and sends the request to the IDP
  • The IDP will authenticate and create a SAML token, however due to problems with Websphere accepting the SAML token we had to write a custom Authentication Handler that generates the SAML token according to Websphere standards
  • The IDP redirect to the Assertion Consumer Provider which is basically a webapp which is deployed on Websphere
  • The ACS checks if the SAML token is correct and uses the username from the token to check if the user exists in it’s local LDAP The IDP contains also a X509 certificate which is used as a identifier…this certificate is used by the ACS to check if the certificate is trusted
  • After all ACS checks (X509 check/ SAML token and LDAP check) have been verified, the user is allowed to access the application
  • The ACS uses the Cookie in order to redirect to the appropriate APP, the name of the cookie is: WasSamlSPReqURL  
The Picketlink Authentication HandlerIn order to implement this handler, we have added a module in JBoss with the following config:

<?xml version="1.0" encoding="UTF 8"?> 
<module xmlns="urn:jboss:module:1.1" name=“companyhandler">
<resources> 
<resource root path="idp idp handler 2.1.8.Final.jar"/>
</resources>
<dependencies>
 <module name="org.picketlink"/>
 <module name="org.picketlink.config"/>
<module name="org.picketlink.federation"/>
<module name="org.picketlink.common"/>
<module name="javax.api"/>
 <module name="javax.servlet.api"/>
<module name="org.picketbox"/>
…..
</dependencies>
</module>
 
The main part is in the companySAML2AuthenticationHandler which is an extension of SAML2AuthenticationHandler…this handle overrides the handleRequestType method….basically it does the same…but in order for Websphere to accept this token it needs to get rid of the InResponseTo attribute…

The following code snippet was added:

Document samlResponse = this.getResponse(request); 
Node entries = samlResponse.getFirstChild();
NamedNodeMap nnm = entries.getAttributes();
nnm.removeNamedItem("InResponseTo");
NodeList nList = samlResponse.getElementsByTagName("saml:SubjectConfirmationData"); 
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
Element eElement = (Element) nNode; nnm = eElement.getAttributes();
nnm.removeNamedItem("InResponseTo");
}

The code is called in the IDP by configuring the following in the webapp/WEB INF/picketlink.xml file


<Handlers xmlns="urn:picketlink:identity federation:handler:config:2.1">
<Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" />
<Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
<Handler class="es.company.jboss_poc.CompanySAML2AuthenticationHandler" />
<Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
<Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" />
</Handlers>

<! The following was commented out…..is replaced by the es.company.jboss_poc.CompanySAML2AuthenticationHandler

<Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />

The Websphere TAI only accepts keys from trusted parties…in the IBM documentation it is stated how to configure the keystore… We made ourselves known to Websphere (The TAI is accepting communication with us) by doing the following:

Created our own keystore:

keytool genkey validity 10000 alias HOSTNAME keyalg RSA keysize 1024 dname "CN=HOSTNAME, O=Company, C=ES” keypass PASSWORD keystore identity.jks storepass PASSWORD

Then we added the keystore to Websphere and make the TAI accept certificates from this keystore
Then we needed to extract the X509 certificate for the alias we are going to use: 

keytool export keystore lnxwaslr18.jks rfc alias lnxwaslr18 

This will give you something like this:

MIICAjCCAWugAwIBAgIEMrRLCDANBgkqhkiG9w0BAQsFADA0MQswCQYDVQQGEwJFUzEQMA4GA1UE ChMHQWxsaWFuejETMBEGA1UEAxMKbG54d2FzbHIxODAeFw0xNTEwMDUxNDQ2MTRaFw00MzAyMjAx NDQ2MTRaMDQxCzAJBgNVBAYTAkVTMRAwDgYDVQQKEwdBbGxpYW56MRMwEQYDVQQDEwpsbnh3YXNs cjE4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqkra4ZxEwExGCb5gerZWEF+dK+iCJag+A z5PIkB/2BP9UP4AomknT93y2czthCDtplzeLGN15UMiURBzdxNtwnMHCr4xku2sFOyuNs7W0yWZ3 9o7Hn1TKvwDfczillKuTF+okP4OllM9mXN5gmietiSrlIwT2kIlzaNAv0MsGHQIDAQABoyEwHzAd BgNVHQ4EFgQUNCK2/WUY51kVN7kyqHU/N4XaH/8wDQYJKoZIhvcNAQELBQADgYEAFUb/efGbZDxq rSw7u6e9j4txbHf+VqtZrVEVkm+r3cNai9vIs7jNzixgaoC6W5kE5x1wtYpkdNjH9EY7SdDFS9EP 7Wt+NI2EdAA3Op50iHjdXiJ5ESHtYNQOFEiTX8+8JglSOAUKacNSdWv0LOm/Ga2GuRe/5LXVfmi5z+eaIIs=

You will need to add the following section in your resources/idp metadata.xml file:

<EntitiesDescriptor Name="urn:mace:shibboleth:testshib:two" ..
<EntityDescriptor entityID="http://lnxwaslr18:8080/idp metadata">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor>
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> <dsig:X509Data>
<dsig:X509Certificate> MIICAjCCAWugAwIBAgIEMrRLCDANBgkqhkiG9w0BAQsFADA0MQswCQYDVQQGEwJFUzEQMA4GA1UE
ChMHQWxsaWFuejETMBEGA1UEAxMKbG54d2FzbHIxODAeFw0xNTEwMDUxNDQ2MTRaFw00MzAyMjAx NDQ2MTRaMDQxCzAJBgNVBAYTAkVTMRAwDgYDVQQKEwdBbGxpYW56MRMwEQYDVQQDEwpsbnh3YXNscjE4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqkra4ZxEwExGCb5gerZWEF+dK+iCJag+A z5PIkB/2BP9UP4AomknT93y2czthCDtplzeLGN15UMiURBzdxNtwnMHCr4xku2sFOyuNs7W0yWZ3 9o7Hn1TKvwDfczillKuTF+okP4OllM9mXN5gmietiSrlIwT2kIlzaNAv0MsGHQIDAQABoyEwHzAd BgNVHQ4EFgQUNCK2/WUY51kVN7kyqHU/N4XaH/8wDQYJKoZIhvcNAQELBQADgYEAFUb/efGbZDxq rSw7u6e9j4txbHf+VqtZrVEVkm+r3cNai9vIs7jNzixgaoC6W5kE5x1wtYpkdNjH9EY7SdDFS9EP 7Wt+NI2EdAA3Op50iHjdXiJ5ESHtYNQOFEiTX8+8JglSOAUKacNSdWv0LOm/Ga2GuRe/5LXVfmi5 z+eaIIs=
</dsig:X509Certificate> </dsig:X509Data>
</dsig:KeyInfo> </KeyDescriptor>

NB: Only the cursive part

Websphereconfiguration is according to these documents:

http://www.ibm.com/developerworks/websphere/techjournal/1307_lansche/1307_lansche.html https://www 01.ibm.com/support/knowledgecenter/SSD28V_8.5.5/com.ibm.websphere.base.doc/ae/twbs_enablesamlsso.html https://www 01.ibm.com/support/knowledgecenter/SSD28V_8.5.5/com.ibm.websphere.base.doc/ae/rwbs_samltaiproperties.html https://www 01.ibm.com/support/knowledgecenter/SS7JFU_8.5.5/com.ibm.websphere.base.doc/ae/cwbs_samlssosummary.html https://developer.ibm.com/digexp/docs/docs/customization administration/step step guide implement saml 2 0 portal 8 5/

Picketlink configuration