Category Archives: Oracle

Oracle: paralelní zpracování

Dnešní databáze běžně obsahují miliony záznamů. Kdyby je měl databázový stroj při každé změně či každém dotazu procházet postupně jeden po druhém, trvalo by to několik hodin. Řešením, které vytěží maximum z dostupného hardware a zvládne úkol v mnohem kratším čase, může být paralelizace. Databáze Oracle verze 11 tuto možnost poskytuje. V článku se podíváme, jak si z pozice administrátora paralelní zpracování na některých databázových objektech vynutit, anebo naopak zakázat, a ukážeme si některé zajímavé parametry, které s paralelizací souvisejí.

 

Continue reading

Úprava schvalovacího workflow v Oracle Identity Managementu


Tento článek popisuje jakým způsobem je možné upravit standardní schvalovací workflow v systému Sun Identity Manager (Oracle Waveset) tak, aby došlo ke schválení i v případě, kdy jeden ze schvalovatelů tuto akci zamítne. Dále zde bude rozebrána funkčnost, kdy jsou schvalovatelé definováni tím, že mají přiřazenou k tomu určenou roli.

Continue reading

Import a export rolí ze Oracle Identity Managementu do CSV


Cílem tohoto článku je ukázat, jakým způsobem je možné exportovat a importovat role ze Sun Identity Manageru (Oracle Waveset).

Jeden z našich klientů, kterému pomáháme v oblasti identity managementu potřeboval, aby z Identity Managera (dále jen IdM) bylo možné vyexportovat role do textového souboru. Exportované soubory s rolemi budou editovat správci jednotlivých systémů a následně bude prováděn hromadný import do IdM.

Continue reading

Vytvoření vlastního resource adaptéru pro Sun Identity Manager


Tento článek popisuje, jakým způsobem je možné naprogramovat vlastní “Standard Resource Adapter” pro produkt Sun Identity Manager, respektive Oracle Waveset 8.1. Při psaní jsem vycházel ze zkušeností, které jsem společně s kolegy nasbíral při programování “univerzálního SSH adaptéru pro unixové systémy (pro Linux, AIX, HP-UX, Solaris a Sambu)” .

Continue reading

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>

Sun IdM Extended Attribute

Atributy, které má Sun Identity Manager (dále IdM) uloženy ve své repository je možné rozšířit o atributy vlastní (Extended Attribute). Jednou z možností, jak to provést je použitím IDM pluginu v NetBeans IDE. Postup je následující: Pravý klik na Custom Identitity Manager Object -> IdM -> Download object. V kategorii Common Configuration Object Types vybereme IdM Schema Configurator.

Chceme-li přidat např. atribut „isBoss“, vložíme do tagu <IDMAttributeConfigurations> následující řádek:

<IDMAttributeConfiguration name='isBoss' description='isBoss flag' syntax='BOOLEAN'/>

Dále do tagu <IDMObjectClassConfiguration name=’User’ extends=’Principal’ description=’User description’> který je podelementem tagu <IDMObjectClassConfigurations> vložíme řádek:

<IDMObjectClassAttributeConfiguration name='isBoss' queryable='true' summary='true'/>

Po uložení změn, provedeme upload souboru do IdM (pravý klik v souboru -> IdM -> Upload Object) a restartujeme aplikační server. Po opětovném načtení tohoto souboru bychom měli v atributech najít „náš“ atribut „isBoss“.

Nyní je možné nastavit uživateli (uživatelům) tento atribut. To je možné např. pomocí následujícího workflow.

<Activity name="fillValue">
	<Action id='0' application='com.waveset.session.WorkflowServices'>
                    <Argument name='op' value='checkoutView'/>
                    <Argument name='id' value='$(accountId)'/>
                    <Argument name='type' value='User'/>
                    <Return from='view' to='view'/>
            </Action>
            <Action name="setup">
                    <set name='view.accounts[Lighthouse].isBoss'>
                        <s>true</s>
                    </set>
            </Action>
            <Action id='2' application='com.waveset.session.WorkflowServices'>
 	      <Argument name='op' value='checkinView'/>
                  <Argument name='view' value='$(view)'/>
             </Action>
             <Transition to='end'/>
             <WorkflowEditor x='122' y='22'/>
</Activity>

Protože jsme u tohoto atributu nastavili parametr „queryable“ na true, je možné podle něj vyhledávat. Následující ukázka je část pravidla (rule), které vyhledá všechny uživatele, které mají nastavený atribut „isBoss“ na true a uloží je do proměnné „users“.

<defvar name="users">
    <invoke name='getUsers' class='com.waveset.ui.FormUtil'>
        <new class='com.waveset.session.InternalSession'/>
            <map>
                <s>conditions</s>
                <list>
                     <new class='com.waveset.object.AttributeCondition'>
                         <s>isBoss</s>
                         <s>equals</s>
                         <s>true</s>
                     </new>
                 </list>
             </map>
     </invoke>
</defvar>

Změna DN v LDAP pomocí Sun IdM workflow

Tento příspěvek ukazuje, jak je možné v Sun Identity Manageru (dále jen IdM) přesunout uživatele z jednoho kontejneru do jiného v adresářovém serveru LDAP.

Zadání zní takto:
Vytvořte workflow, které dostane vstupní parametry accountId a sluzebnatext. Workflow ověří jestli dn, které se z těchto parametrů složí je shodné jako to, které získá z uživatelského view. Pokud se dn nebudou shodovat, dojde k přesunutí uživatele.

Můj postup byl následující:
Nejprve bylo nutné získat uživatelské view pro uživatele, jehož accountId jsem dostal na vstupu.


<Activity id='1' name='findDataInView'>
  <Action application='com.waveset.session.WorkflowServices'>
    <Argument name='op' value='getView'/>
    <Argument name='viewId'>
     <concat>
        <s>User:</s>
        <ref>accountId</ref>
     </concat>
    </Argument>
    <Return from='view' to='view'/>
  </Action>
  <Transition to='isDnSame'>
    <notnull>
      <ref>view</ref>
    </notnull>
  </Transition>
  <Transition to='end'/>
  <WorkflowEditor x='176' y='112'/>
</Activity>

Z view jsem dostal firstname a lastname, ze kterých jsem odstranil diakritiku pomocí funkce napsané v jazyku Java. Diakritiku jsem odstranil i ze vstupního parametru sluzebnatext. Pomocí rule jsem poté mohl zkonstruovat DN a uložit jej do proměnné dnNew (pro lepší představu: v hodnotě dnNew může být např. následující String: „cn=Jmeno Prijmeni,ou=Budova 1,o=Pobocka 1,ou=People,o=Firma,c=cz“). Dalším krokem (akcí) bylo nastavení DN, které jsem získal z view do proměnné dnFromView.

<Activity id='2' name='isDnSame'>
   <Variable name="firstname">
     <invoke name='removeDiacritic' class='cz.bcvsolutions.util.Text'>
       <ref>view.accounts[Lighthouse].firstname</ref>
     </invoke>
   </Variable>
   <Variable name="lastname">
     <invoke name='removeDiacritic' class='cz.bcvsolutions.util.Text'>        <ref>view.accounts[Lighthouse].lastname</ref>
     </invoke>
   </Variable>
   <Action id='0' name='removeDiacritic'>
     <expression>
       <setvar name='sluzebnaText'>
        <invoke name='removeDiacritic' class='cz.bcvsolutions.util.Text'>
         <ref>sluzebnaText</ref>
        </invoke>
      </setvar>
     </expression>
   </Action>
   <Action id='1' name="createDN">
     <expression>
     <setvar name='dnNew'>
       <rule name="BCV Create Dn">
         <argument name="firstname" value="$(firstname)"/>
         <argument name="lastname" value="$(lastname)"/>
         <argument name="sluzebnatext" value="$(sluzebnaText)"/>
       </rule>
     </setvar>
     </expression>
   </Action>
   <Action name="setupDNFromView">
     <set name="dnFromView">
       <ref>view.waveset.accounts[Logserver].accountId</ref>
     </set>
   </Action>
   <Transition to="moveUser">
     <neq>
       <ref>dnNew</ref>
       <ref>dnFromView</ref>
     </neq>
   </Transition>
   <Transition to='end'/>
   <WorkflowEditor x='23' y='113'/>
</Activity>

Pokud se DN liší (např. mohlo dojít ke změně jména, či přesunu pracovníka do jiné pobočky), dojde ke skoku do aktivity s názvem „moveUser“, ve které dojde k přejmenování uživatele. Je nutné udělat checkoutView, nastavit v požadovaném zdroji (Resource) novou identitu, nastavit v požadovaném zdroji příznak, že došlo ke změně a poté udělat checkinView.

<Activity name="moveUser">
   <Action id='0' application='com.waveset.session.WorkflowServices'>
     <Argument name='op' value='checkoutView'/>
     <Argument name='id' value='$(accountId)'/>
     <Argument name='type' value='RenameUser'/>
     <Return from='view' to='renameUserView'/>
   </Action>
   <Action name="changeDN">
     <expression>
       <block>
       <set name='renameUserView.accounts[Logserver].identity'>
         <ref>dnNew</ref>
       </set>
       <set name='renameUserView.resourceAccounts.currentResourceAccounts[Logserver].selected'>
         <i>1</i>
       </set>
       </block>
     </expression>
   </Action>
   <Action id='2' application='com.waveset.session.WorkflowServices'>
     <Argument name='op' value='checkinView'/>
     <Argument name='view' value='$(renameUserView)'/>
   </Action>
   <Transition to='end'/>
   <WorkflowEditor x='294' y='240'/>
</Activity>

Nyní došlo k přejmenování uživatele systému LDAP.

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>