All posts by Jan Gregor

Správa účtů v XML souborech a jejich distribuce

V tomto článku popíši, jak jsem pomocí IdM řešil správu účtů v XML souboru. Tento soubor je zdrojem účtů pro aplikaci běžící v tomcatu a je načítán pouze při startu. Po editaci souboru je proto potřeba tomcat restartovat. Aplikace běží na dvou serverech, před kterými je loadbalancer, jež mezi ně rozhazuje požadavky. XML soubory je tedy potřeba udržovat na obou dvou serverech. Navíc je požadováno, aby bylo možno ručně soubor modifikovat.

Požadavky by se daly shrnout následovně:

  • Přidávat, editovat a odstraňovat záznamy v souboru.
  • Změny musí být propagovány na oba dva servery.
  • Aplikace musí být po aktualizaci souboru restartována.
  • Vždy musí být dostupná alespoň jedna aplikace.
  • Soubor může být ručně editován.

Continue reading

Schvalování v CzechIdM

V následujícím textu se snažím zevrubně popsat problematiku okolo schvalování v kontextu správy identit pomocí CzechIdM. Nejdříve vysvětlím, co pojmem “schvalování” myslím a také uvedu pár výhod, které přináší použití správce identit. Poté se podíváme na tuto problematiku očima uživatele a administrátora CzechIdM. Později se dostanu i k tomu, jak je schvalování v našem systému realizováno.
Continue reading

Identity Manager – Jak připojit systém Vema

U zákazníka v ČR jsme připojovali náš Identity Manager CzechIdM na personalistiku od brněnské firmy Vema. Aplikace Vema je využívána pro evidenci zaměstnanců, a proto představuje primární zdroj informací o uživatelích. CzechIdM má na starosti správu uživatelských účtů postupně ve všech systémech organizace zákazníka. V tomto příspěvku tedy popíši, jak jsme řešili napojení CzechIdM na systém Vema.

Continue reading

Identity manager – jak funguje propojení konektor / cache / vyhledávání

Tento příspěvek vzniknul úpravou dotazu a mé odpovědi na webu http://www.abclinuxu.cz

Jak to v Identity Manageru (IdM) vlastně pořádně funguje? Jak jsou načítány a ukládány údaje z koncových systémů? Dejme tomu že mám uživatele v Active Directory či nějaké SQL databázi. Každý uživatel může mít několikrát definován nějaký atribut (třeba skupina). Když k tomu budu chtít připojit Identity Manager, jak se s těmito atributy vypořádá?

Continue reading

Blokování účtů v CzechIdM

Jednou ze základních schopností každého identity manageru je blokování účtů na připojených koncových systémech. Náš CzechIdM nabízí několik možností jak tuto operaci provést. V tomto krátkém článku probereme každou z nich.

CzechIdM lze pro každý systém nakonfigurovat jedním z následujících způsobů – blokování resetem hesla – pro zablokování účtu volat pravidlo – bez nějaké zvláštní podpory blokování (lze využít mapování atributů – viz níže)

 

Continue reading

Sun Certified Java Programmer

Tak jsem se zúčastnil mého prvního testu na certifikaci. A protože o tom tady píšu, tak je jasné, že jsem ho i udělal :-) Konkrétně šlo o Sun Certified Programmer for the Java Platform, Standard Edition 6 (CX-310-065).

Vzhledem k tomu, že jsem nevěděl do čeho jdu, tak jsem se snažil ve chvilkách volného času učit. Pro přípravu je bezvadná, i když často zbytečně podrobná, tato knížka http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060/ref=sr_1_1?ie=UTF8&s=books&qid=1269886588&sr=1-1 Na konci každé kapitoly je seznam nejdůležitějších znalostí a hlavně ukázkové příklady.

Když to teď porovnám s těmi v reálném testu, tak musím říct, že v té knížce mi připadaly mnohem zákeřnější.
Například nějaký složitější zdrojový kód a vy máte určit, co bude jeho výsledkem. No a odpověď byla, že to nepůjde zkompilovat, protože tam chybí jeden import. Na druhou stranu vás to aspoň vycvičí v pozornosti, což se mi několikrát během ostrého testu hodilo.

No, abych to uzavřel, velká část otázek mně přišla nesmyslná. Týkaly se totiž toho, co za vás zkontroluje kompilátor. Na druhou stranu, jsem se během studia občas dozvěděl něco nového a také už snad nebudu muset tak často hledat v dokumentaci :-).

Také je dobré, že se na konci testu dozvíte, jak jste dopadli v jednotlivých oblastech. Detailní popis zkoušených oblastí najdete na této stránce http://in.sun.com/training/catalog/courses/CX-310-065.xml

Sun-Oracle IdM: Zobrazení approval work items všech uživatelů

V administračním rozhraní Sun Identity Manageru (dále jen IdM) na záložce Work Items -> Approvals je možnost vylistovat a následně pracovat se schvalovacími work itemy všech schvalovatelů, tzn. těch, co mají přiřazenou administrační roli “Approver Administrator”.

V jednom projektu jsme ale museli řešit problém, jak na tomto formuláři přidat možnost pracovat se všemi schvalovacími položkami, tedy i s položkami, které patří obyčejným uživatelům.
Konkrétně jde o formulář “Work Item List”, který prezentuje data z pohledu “WorkItem List View”.
Jak se dá dočíst v dokumentaci (http://docs.sun.com/app/docs/doc/820-5821/bvbjl?l=en&a=view&q=WorkItemList), tento pohled obsahuje atribut “workItems”.

Proto se nabízí řešení, naplnít tento atribut vlastním seznamem položek. Ty jde získat například použitím metody “com.waveset.ui.FormUtil.getObjectNames” s parametrem “WorkItem” v kombinaci s metodou “com.waveset.ui.FormUtil.getObject”. Potom je ještě potřeba vytvořit GenericObject atd. Výsledkem je, že se sice položky v seznamu objeví a pokud se podíváme na jejich detail, tak jdou i schválit. Nicméně, pokud v seznamu označíme více položek a ty chceme například schválit, nic se nestane.

Po dekompilaci (pomocí JAD) a prozkoumání příslušného view handleru (com.waveset.view.WorkItemListViewer v balíčku “idm.jar”) zjistíme, že ve výše zmiňovaném případě, je ve view handleru znovu vytvořen seznam work itemu, který se prochází položka po položce a kontroluje se, jestli je obsažena v seznamu těch námi vybraných. Proto, i když v tomto seznamu vybraných položek bude nějaká nová (od obyčejného uživatele), tak se vůbec nebude zpracovávat.

Celý problém se nakonec podařilo vyřešit vytvořením vlastního view handleru “MyWorkItemListViewer” na základě dekompilovaného “WorkItemListVieweru”. Jediné, co bylo potřeba změnit, byla metoda “processQueryResult”. V jejím těle si přečteme hodnotu našeho parametru, který nám říká, jestli se mají zobrazit všechny položky nebo ne.

boolean getAll = view.getBoolean("getAllWorkItems");

A o pár řádku níže, kde se kontroluje, jestli “owner” je v “controlledUsers”, tuhle hodnotu použijeme. My jsme třeba celou podmínku, která tento blok obaluje, změnili z:

if(accountId == null)

na

if(accountId == null && !getAll)

Tím pádem, pokud bude “getAll” nastaveno na “true”, tak se vůbec nebude provádět kontrola, jestli vlastník work itemu je v seznamu “controlledUsers”.

Handler musí být umístěn v balíčku “com.waveset.view”. Aby se použil náš view handler, zmeníme v “approval/approval.jsp” příkaz

form.setViewId("WorkItemList");

na

form.setViewId("MyWorkItemList");

Poslední věc, kterou je ještě potřeba udělat, je zajistit, aby v combo-boxu na formuláři “Work Item List” byla možnost “All users”. Po jejím vybrání se nastaví atribut pohledu “user” na hodnotu “null” a také náš atribut “getAllWorkItems”. Nulová hodnota atributu “user” zajistí, že se bude provádět kód view handleru, kde se používá náš atribut.

Pole “user” jsme upravili následovně:

         <Field name='getAllWorkItems'>
              <Expansion>
                  <eq>
                      <ref>userCombo</ref>
                      <s>___ALL_APPROVAL_ITEMS___</s>
                  </eq>
              </Expansion>
          </Field>
          <Field name='user'>
              <Expansion>
                  <cond>
                      <eq>
                          <ref>userCombo</ref>
                          <s>___ALL_APPROVAL_ITEMS___</s>
                      </eq>
                      <null/>
                      <ref>userCombo</ref>
                  </cond>
              </Expansion>
          </Field>
          <Field name='userCombo'>
            <Display class='Select'>
              <Property name='command' value='Recalculate'/>
              <Property name='nullLabel' value='UI_APPR_JAVA_ALL_APPROVERS'/>
              <Property name='valueMap'>
                  <block>
                      <defvar name="values">
                          <list>
                              <s>___ALL_APPROVAL_ITEMS___</s>
                              <s>UI_APPR_JAVA_ALL_USERS</s>
                          </list>
                      </defvar>
                      <invoke name="sort" class="java.util.Collections">
                          <ref>users</ref>
                      </invoke>
                      <dolist name="user">
                          <ref>users</ref>
                          
                          <append name="values">
                              <ref>user</ref>
                              <ref>user</ref>
                          </append>
                      </dolist>
                      <ref>values</ref>
                  </block>
              </Property>
           <!--   
              <Property name='allowedValues' value='$(users)'/> 
              <Property name='sorted' value='true'/>
           -->
            </Display>
          </Field>

Výčtový typ v jazyku Java

Od verze javy 5.0 jsou k dispozici výčtové typy, které přináší především zvýšení typové bezpečnosti.
Definice a použití jednoduchého výčtového typu je podobná jako v jazycích C/C++.
Například:

enum Color { RED, GREEN, BLUE }

Color color = Color.BLUE;
//...
switch (color) {
    case BLUE:
        //do something
        break;
    default:
        //do something
}

Na rozdíl od C nebo C++ je enum v javě mnohem mocnější. Výše uvedenou definici si lze představovat jako zkratku za

class Color {
    public static final Color RED   = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE  = new Color();
    
    protected Color() {}
}

Proto je možné definovat uvnitř enumu metody nebo přidávat atributy, což jde vidět v následujícím příkladu.
Je zde uveden výčtový typ plemen psů. U každého plemene chceme mít uvedenou minimální váhu a výšku v kohoutku.
Navíc umí každé plemeno psa štěkat. Protože jediný československý vlčák štěká česky, přepíšeme jeho metodu bark.
Také přepíšeme metodu toString tak, aby se názvy plemen vypisovaly malými písmeny a místo podtržítek byly mezery.

enum DogTribe {
    GERMAN_SHAPHERD_DOG(61, 30),
    GIANT_SCHNAUZER(65, 32),
    CZECHOSLOVAKIAN_WOLFDOG(65, 26) {
        @Override
        public String bark() {
            return "haf-haf";
        }
    };

    public String bark() {
        return "bow-wow";
    }

    public int getDogMinHeight() {
        return this.dogMinHeight;
    }

    public int getDogMinWeight() {
        return this.dogMinWeight;
    }

    @Override
    public String toString() {
        return this.name().toLowerCase().replace('_', ' ');
    }

    private DogTribe(int dogMinHeight, int dogMinWeight) {
        this.dogMinHeight = dogMinHeight;
        this.dogMinWeight = dogMinWeight;
    }

    private int dogMinHeight; //measured in cm in withers
    private int dogMinWeight; //measured in kg
}

public class Main {
    public static void main(String[] args) {
        for (DogTribe tribe: DogTribe.values()) {
            System.out.println(tribe);
            System.out.println("\tMinimal height: " + tribe.getDogMinHeight());
            System.out.println("\tMinimal weight: " + tribe.getDogMinWeight());
            System.out.println("\t" + tribe.bark());
        }
    }
}

Připojení Sun Identity Manageru k SAP Basis

Tento příspěvek stručně informuje o problematice připojení SAPu (testováno na verzi SAP R/3) k Sun Identity Manageru (IdM) a popisuje pár praktických příkladů.

SAP Basis (business application software integrated solution) mimo jiné obsahuje sadu nástrojů pro administraci systému a uživatelů SAPu. Právě druhé zmíněné nás zajímá. Naším cílem je napojení Sun Identity Manageru (IdM), tak abychom pomocí něho mohli spravovat uživatele.

Pro připojení externích programů je v SAPu k dispozici Business Application Programming Interface (BAPI). Funkce tohoto rozhraní můžou být z javy volány přes RFC díky knihovně SAP JCo (Java Connector). Takto knihovna je nyní dostupná ve dvou navzájem nekompatibilních verzích, kterým odpovídají dva různé adaptéry v IdM.

Při použití starší, dvojkové verze knihovny, je potřeba přidat do Custom Resources třídu com.waveset.adapter.SAPResourceAdapter. U novější, trojkové verze, se používá třída com.waveset.adapter.SAPBasisResourceAdapter. Je ještě třeba dodat, že podpora SAPBasisResourceAdapter byla přidána do verze IdM 8.1 až patchem číslo dva. Tím také byl starší adaptér označen jako deprecated a od IdM 9 nebude nadále podporován. Konfigurace adaptéru je velmi podobná, nově je třeba specifikovat Destination Name. To označuje spojení a musí být v rámci JVM jedinečné.

Samotná instalace knihovny a konfigurace adaptéru je dobře dokumentována zde http://docs.sun.com/app/docs/doc/820-6551/giiyg?l=en&a=view

Na straně SAPu je potřeba přidat uživatelovi, přes kterého se IdM připojuje a spravuje uživatele, práva na funkční skupiny. Viz
http://help.sap.com/javadocs/NW04s/current/jc/com/sap/mw/jco/JCO.Repository.html

I po nastavení všech práv uvedených na odkazované stránce může stále docházet k problémům (nejen) z důvodu nedostatečných oprávnění. Proto se hodí možnost nastavit logování činnosti JCO knihovny. Děje se tak na stránce pro editaci resource parametru v polích SAP JCO Trace Level a SAP JCO Trace Directory. Nejvíce mi pomohly soubory after-*.xml, ve kterých je uvedeno, které BAPI funkce byly volány a jaký byl jejich výstup.

S rolemi, které jsou přiřazeny učtu, se pracuje přes atribut activityGroups. V resource schema by mělo být nastaveno mapování activityGroups na ACTIVITYGROUPS. Ve starší verzi adaptéru se dá ještě použít mapování na ACTIVITYGROUPOBJECTS nebo ACTIVITYGROUPS->AGR_NAME (pracuje se pouze s názvy rolí).

Pro ukázku, jak se pracuje s rolemi v případě mapování na ACTIVITYGROUPS, uvedu dva příklady.
Používají se objekty tříd GenericAttribute a GenericObject. Jejich dokumentaci naleznete v adresáři [stazene_idm]/REF/javadoc nebo pro idm7 na http://www-users.york.ac.uk/~jdi500/idm/javadoc/index.html
Jak vypadá struktura atributu activityGroups je vidět na následujícím xmlku.

<GenericAttribute>
  <Object>
    <Attribute name='attribute'>
      <Object>
        <Attribute name='activityGroups'>
          <List>
            <Object name='NAZEV_ROLE11/25/2009'>
              <Attribute name='AGR_NAME' value='NAZEV_ROLE'/>
              <Attribute name='AGR_TEXT' value='Popis role'/>
              <Attribute name='FROM_DAT' value='11/25/2009'/>
              <Attribute name='ORG_FLAG'/>
              <Attribute name='TO_DAT' value='12/31/9999'/>
            </Object>
          </List>
        </Attribute>
      </Object>
    </Attribute>
  </Object>
</GenericAttribute>

1) Získání seznamu názvů rolí, přiřazených konkrétnímu účtu.

<dolist name="role">
    
    <invoke name="get">
        <invoke name="get">
            <ref>accounts[%%RES_SAP%%].activityGroups</ref>
        </invoke>
        <s>activityGroups</s>
    </invoke>
    
    <get>
        <invoke name="getAttributes">
            <ref>role</ref>
        </invoke>
        <s>AGR_NAME</s>
    </get>
    
</dolist>

2) Vytvoření rolí ze seznamu jejich názvu a uložení do atributu.
Pokud se nenastaví hodnoty FROM_DATE a TO_DATE, tak se automaticky doplní na aktuální datum, respektive na 12/31/9999.
Jestliže je nastavit chceme, jednoduše je doplníme do mapy v konstruktoru GenericObjectu uvedené v tomto příkladu.

<defvar name='agListGo'>
    <new class="com.waveset.object.GenericObject" >
        <map>
            <s>activityGroups</s>
            <list />
        </map>
    </new>
</defvar>

<dolist name="name">
    <ref>activityGroupNames</ref>

    <block>
        <invoke name="add">
            <ref>agListGo</ref>
            <s>activityGroups</s>

            <new class='com.waveset.object.GenericObject'>
                <map>
                    <s>AGR_NAME</s>
                    <ref>name</ref>
                </map>
            </new>

        </invoke>
        
    </block>
</dolist>

<setvar name="accounts[%%RES_SAP%%].activityGroups">
    <new class="com.waveset.object.GenericAttribute">
        <ref>agListGo</ref>
    </new>
</setvar>

Dále se ještě může hodit získání seznamu všech dostupných rolí.
K tomu potřebujeme mít nastavena práva na čtení z tabulky AGR_DEFINE.
Role jsou pak získány následujícím kódem.

<invoke name='listResourceObjects' class='com.waveset.ui.FormUtil'>
    <ref>:display.session</ref>
    <s>activityGroups</s>
    <s>%%RES_SAP%%</s>
    <null/>
    <s>true</s> <!-- Pouzivat cache? -->
</invoke>