All posts by Adam Lenger

CzechIdM – Java – E-mails with attachment

Last week we’ve learned our Identity Manager CzechIdM how to send e-mails with attachments. There are plenty of situations where it could be used: pre-filled form in PDF for print, configuration file for new VPN, certificate or actual version of phone list. I will introduce you this functionality in this article. You will learn how to use it and we will look how to create instance of class MimeMessage, which is used for sending e-mails from Java.

Application Class

Identity Manager CzechIdM has 3 standard layers – data, application and presentation layer. Sending e-mails is of course in application layer – this service is mostly provided to processes, which are written specially for customer. Universal interface of application layer for customer’s processes is Application class. In this class are a lot of useful static methods used by programmers and administrators, from logging to audit log to checking the rights of logged user.

For sending e-mails there are two static methods: sendEmailToIdentity and sendEmailToAddress. Both of them are overloaded, therefore they exist in more versions with different number of arguments. We will discuss only those most general which are using the biggest number of arguments. They’re:

Application.sendEmailToIdentity(String userName, String emailTemplate, Map params, String language, List<EmailAttachment> attachments)
Application.sendEmailToAddress(String address, String emailTemplate, Map params, String language, List<EmailAttachment> attachments

Calling of methods

Argument userName or address defines addressee of the message (by name of identity in CzechIdM or directly by e-mail address), emailTemplate defines template, which is used to assemble message and params is for attributes of message, which will be input into the template. With argument language you can choose language for the situation, when template exists in more language versions. If you input null, the first found template is choosed. Last argument – attachments – is new and is for list of attachments to send.

Instance of class EmailAttachment stands for one attachment. CzechIdM can send attachments in two ways – it can send existing file from disc or dynamically generated array of bytes. Class EmailAttachment represents only encapsulated information about one attachment, as programmer or administrator you can go with 2 constructors:

EmailAttachment(String path, String fileName)
EmailAttachment(byte[] bytes, String mimeType, String fileName)

First is for attachment saved in existing file at disc (path to file is in argument path), second is for sending array of bytes (argument bytes). You can rename attachment with the argument fileName for the addressee. Argument mimeType enable closer specification, how the bytes should be interpreted – picture, text, video…

Example

Following code sends attachment by both methods, as array of bytes and as existing file from disc:

import eu.bcvsolutions.idm.app.Application;
import eu.bcvsolutions.idm.app.email.EmailAttachment;
HashMap params = new HashMap();

    //mapa parametru. Temito parametry bude doplnena e-mailova sablona, #{attr1} v sablone bude nahrazeno retezcem "val1"
    params.put("attr1", "val1");
    params.put("attr2", "val2");
    params.put("attr3", "val3");

    //seznam priloh, ktere v mailu odesleme
    List attachments = new ArrayList();
    //prilohy lze pridat dvema zpusoby - bud primym predanim cesty k souboru a nazvu, pod jakym ma byt predan uzivateli
    EmailAttachment attach1 = new EmailAttachment("/opt/attachments/ahoj.txt", "ahoj.txt");
    //nebo primym predanim pole bytu vcetne mime typu a nazvu souboru
    byte[] bytes = {0x41, 0x48, 0x4F, 0x4A};
    EmailAttachment attach2 = new EmailAttachment(bytes, "text/plain", "ahoj.txt");

    attachments.add(attach1);
    attachments.add(attach2);

    Application.sendEmailToAddress("moje.adresa@test.com", "sablonaTestovaci", params, "cz", attachments);

How it works

The most important part of code is assembling MimeMessage, instance of class, which will be subsequently send. In CzechIdM is this task processed by old method createMimeMessage in class IdMMailerQueueListener. Unusual is using of class Multipart, which enables completing message from more parts, while some of them are mentioned attachments:

private MimeMessage createMimeMessage(Session session, MapMessage mapMessage) throws AddressException, MessagingException, JMSException {
        Charset charset = Charset.forName("UTF-8");

        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(mapMessage.getString(Constants.EMAIL_FROM)));

        InternetAddress [] recipients = { new InternetAddress(mapMessage.getString(Constants.EMAIL_TO)) };
        mimeMessage.setRecipients(javax.mail.Message.RecipientType.TO, recipients);
        mimeMessage.setSubject(mapMessage.getString(Constants.EMAIL_SUBJECT), charset.name());
        mimeMessage.setSentDate(new java.util.Date());

        Multipart multipart = new MimeMultipart();
        // cast s textem
        MimeBodyPart messageBodyPart = new MimeBodyPart();
        //naplnim cast textem
        messageBodyPart.setText(mapMessage.getString(Constants.EMAIL_CONTENT), charset.name());
        messageBodyPart.setHeader("Content-Type", mapMessage.getString(Constants.EMAIL_CONTENT_TYPE) + "; charset=" + charset.name());
        multipart.addBodyPart(messageBodyPart);

        //zpracovani priloh, ktere jsou z technickych duvodu predany serializovane
        byte[] serializedList = mapMessage.getBytes(Constants.EMAIL_ATTACHMENTS);
        ObjectInputStream ois = null;
        List&lt;EmailAttachment&gt; attachs = new ArrayList&lt;EmailAttachment&gt;();
        if (serializedList != null) {
            try {
                ois = new ObjectInputStream(new ByteArrayInputStream(serializedList));
                attachs = (List&lt;EmailAttachment&gt;) ois.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
            e.printStackTrace();
            } finally {
                if (ois != null) {
                    try {
                        ois.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        //postupne pridam do zpravy vsechny prilohy, ktere mi byly zadany
        for (EmailAttachment attach : attachs) {
            messageBodyPart = new MimeBodyPart();
            DataSource source = null;
            //podle typu prilohy se rozhodnu, jak budu nacitat data
            switch(attach.getType()) {
            case FILE:
                File attachment = new File(attach.getFilePath());
                if (!attachment.canRead() || attachment.isDirectory() || attachment.isHidden()) {
                    Application.logError("Attachment " + attachment.getAbsolutePath() + " was not sent!", new Object[0]);
                    throw new RuntimeException("Attachment failed: " + attach.getFilePath());
                }
                source = new FileDataSource(attachment);
                break;
            case BYTES:
                source = new ByteArrayDataSource(attach.getBytes(), attach.getMimeType());
                break;
            default:
                throw new RuntimeException("Unknown EmailAttachment Type " + attach.getType());
            }

            messageBodyPart.setDataHandler(new DataHandler(source));
            messageBodyPart.setFileName(attach.getFileName());
            multipart.addBodyPart(messageBodyPart);
        }

        // pridam vsechny casti do zpravy
        mimeMessage.setContent(multipart);

        mimeMessage.saveChanges();
//zprava je pripravena k odeslani
        return mimeMessage;
    }

Conclusion

In this article we taught you how to send e-mail with attachment through CzechIdM. You also have chance to see one of the key procedures of application layer, which is using usual mechanisms of Java.

Kerberos at CTU – case study

Czech Technical University (CTU) is significantly heterogeneous environment from the view of information systems. It counts tens to hundreds standalone services and applications, which are used by tens of thousands users – students, employees and hosts. What is specific for CTU environment is splitting administration and service of IT between university and faculty departments.

Introduction

System Kerberos was introduced to CTU as modern and safe system of central authentication and authorization enabling user to use one password to all systems across the whole environment of CTU. Creating, updating and deleting of user accounts is done automatically by identity manager Oracle Waveset (IdM), which is administrated and developed by BCV solutions s.r.o. Goal of introducing system Kerberos was to set central authentication point, which will be used by all university and faculty systems.

Solution

Basic request to solution was to completely automate life cycle of user account at Kerberos system. To every user, who is created in some of source systems at CTU, for example to database of students or to personal system, is created new account at Kerberos through IdM. In the moment, when user ends study or job, is his account automatically deactivated.

Stand-alone chapter of task was administrating of passwords. Used solution enables changing of password through web interface of IdM, which was adjusted to customer’s needs. Besides of basic users there are users with advanced privileges, so called administrators of passwords. These administrators can change password to every user from their scope – for example faculty or department. Every new password is checked for security reasons; administrator can set policy, which password needs to fullfil.

All communication is done only by encrypted channels: HTTPS or SSH.

User interface

Schedule of deployment

2013/02 – Start of project, analysis

2013/03 – Implementation, adjustment of user interface, testing

2013/04 – Accepted by customer, used in production environment

Benefits for customer

  • Centralization – change of password is propagated to more applications only by one web form.
  • Security – all communication is done by safe protocols.
  • Auditability
  • User autonomy – student can change his password by himself

Conclusion

In this case study you have chance to get know process of deployment Kerberos at Czech Technical University. If this basic summary is not enough for you and you want to know more, email me at: adam.lenger@bcvsolutions.eu

 

Odložené úkoly – Deffered Tasks v Oracle Waveset

Ve většině společností se účty zaměstnanců spravují k určitému datu. Při nástupu zaměstnance se mu jeho uživatelské účty (email, přístup do informačních systémů dané společnosti atd.) zpřístupní k datu jeho nástupu. Při jeho odchodu se mu naopak účty zablokují, případně smažou, k datu jeho odchodu. Níže Vám nastíním jednu z možností, jak takové řešení implementovat.

Nedávno jsme u jednoho zákazníka řešili následující úkol. Pravidelný proces, který kontroloval a aktualizoval všechny identity uživatelů každý den, se postupně s více napojenými systémy zpomalil a bylo ho potřeba nahradit úspornějším a stejně funkčním řešením. Tento proces prováděl kontrolu platnosti účtů u všech identit a podle toho případně přidával či odebíral role, tj. zakládal či blokoval uživatelské účty. U drtivé většiny identit ale žádná změna neprobíhala. Bylo tedy potřeba vytvořit proces, který se spustí pouze nad identitami, kde má proběhnout nějaká změna, např. nad zaměstnanci, jimž dnes končí pracovní poměr.

Vzhledem k tomu, že u tohoto zákazníka je nasazen Oracle Waveset, bylo možné částečně použít řešení Deffered Tasks (Odložené úkoly).

clocks

Deffered Tasks

O co se tedy vlastně jedná? V Oracle Waveset se vyskytuje standardní funkce Deffered Tasks, která umožňuje u dané identity uložit, kdy a jaký proces se má nad ní spustit. Dále je zde možné nastavit, zda se má daný proces provést pouze jednou, nebo opakovaně. Spouštění těchto tasků zajišťuje další proces – Deffered Task Scanner. Ten je spouštěn v pravidelných intervalech a zpracovává deffered tasks z minulosti. Prochází tedy pouze identity, které u sebe mají nastavené spuštění úkolu s datem v minulosti. U těchto identit spustí specifikovaný proces s parametry, které je také možné uložit u identity. Po skončení vypíše seznam identit, spouštěné procesy a výsledek.

Nasazení v našem případě

V našem konkrétním případě tedy stačí, když při každé změně data konce či začátku daného účtu bude spuštěn proces, který provede potřebné kroky. Toto datum se načítá při synchronizaci. Bylo ji tedy třeba upravit tak, aby případně k uživateli uložila odložený úkol. Příklad uložení můžete vidět níže:

<Property name='tasks'>
  <List>
    <Object name='Deffered Task'>
      <Attribute name='date'>
	<Date>2014-03-02T23:00:00.000Z</Date>
      </Attribute>
      <Attribute name='description' value='2014-03-03'/>
      <Attribute name='executeOnce' value='true'/>
      <Attribute name='accountId' value='100001'/>
    </Object>
  </List>
</Property>

Poté bylo potřeba pouze nastavit pravidelné spouštění Deffered Task Scanneru, který již bude potřebné operace spouštět každý den v pravidelnou dobu.

Tato úprava tedy nahradila zbytečně velký, dlouhý a náročný proces za optimálnější řešení, které funguje přesně na identitách, na kterých má, a neprovádí zbytečné úkony navíc. Bylo potřeba samozřejmě dopsat proces, který se spouští na zadaných identitách v zadanou dobu.

Možnost nasazení jinde

Toto řešení lze samozřejmě implementovat i v jiných podobných systémech. Data, která se ukládají k objektům, navíc nejsou nijak velká, tedy nevznikne ani velký nárok na další paměť. Pravidelný proces pro vykonávání těchto akcí se dá naplánovat na námi požadovanou dobu a tím pádem lze určit, kdy poběží tato akce, která může být v některých případech časově náročná. Navíc máme kontrolu nad tím, kdy a pro jakého uživatele se daná akce spouští. Tím pádem se vždy po doběhnutí pravidelného procesu můžeme podívat na potřebné výsledky a nemusíme je hledat mezi spoustou dalších pro nás nepotřebných záznamů.

Závěr

V tomto článku  je popsáno využití odložených úkolů v konkrétním případě. Toto řešení lze určitě aplikovat i na mnoho dalších problémů. Pokud byste měli nějaké dotazy ohledně našeho řešení, či nějaké další dotazy ohledně Oracle Waveset, neváhejte mě kontaktovat na adam.lenger@bcvsolutions.eu.

Vytvoření formuláře v Oracle Waveset

Oracle Waveset nám nabízí mnoho standardních formulářů, ale občas je třeba vytvořit jeden specifický, který se mezi nimi nevyskytuje. S takovýmto problémem jsme se setkali i u nás a to v situaci, kdy bylo potřeba vytvořit formulář pro změnu hesla na nově připojeném systému. Je to centrální autentizační systém. Tento nový formulář slouží běžným uživatelům ke změně svého hesla, správcům potom ke změně hesla normálním uživatelům, kteří spadají do jejich oblasti působnosti (tato oblast je určována podle přiřazené role).

Continue reading

Vylepšení IdMUploaderu pro CzechIdM

IdMUploader je v CzechIdM velmi často používaný nástroj, který slouží vývojářům k uploadu workflow, pravidel a e-mailových šablon. Při používání vyvstalo několik úkolů ke zlepšení efektivní práce:

  1. Zajistit přenositelnost z MySQL na jakýkoliv jiný databázový engine, například Oracle a PostgreSQL.
  2. Umožnit refresh workflow přímo z IdMUploaderu. Tuto akci bylo dříve nutno provádět ručně, až po uploadu workflow, přes webové rozhraní.
  3. Poslední přidanou věcí je spouštění přes bash skript se zadanými argumenty.

V následujícím článku popíši jednotlivé změny a načrtnu, jak jsem dané řešení implementoval.

Continue reading

Připojení finančního informačního systému do IdM

Na podzim tohoto roku jsme připojovali finanční informační systém (dále zde označován pod zkratkou FIS) pro vysokou školu od dodavatele BBM. Na této univerzitě již běží Identity Manager Sun/Oracle Waveset, kde je již několik systémů připojených. V tomto článku vás seznámím s průběhem připojení a také s problémy, které při tom nastaly.

Zadání

Identity Manager má za úkol na FISu spravovat uživatele. Přidává nebo odebírá role a také mění jeho atributy. Role ale nevytváří, needituje ani neodstraňuje.
Continue reading