Warning: Declaration of Suffusion_MM_Walker::start_el(&$output, $item, $depth, $args) should be compatible with Walker_Nav_Menu::start_el(&$output, $item, $depth = 0, $args = Array, $id = 0) in /DISK2/WWW/plsql.cz/www/wp-content/themes/suffusion/library/suffusion-walkers.php on line 0
Jan 272014
 

Další z novinek ;) Tentokrát to bude velice krátké, pro dnešek jsem vybral novou funkci, která je dostupná ve dvanácce a jmenuje se STANDARD_HASH. A její účel asi nikoho nepřekvapí – vrací zahashovaný vstup s tím, že k dispozici jsou následující algoritmy pro hash:

  • SHA1 (deafult) – 160bitů. Je třebas připomenout, že SHA1 byla z kryptografického hlediska (nikoliv uživatelského) prolomena a kolizi jsme schopni nalézt dříve než v teoretických 2^80, konkrétně podle wikipedie v 2^61. Což je pouze prolomeno z té teoretické části, z praktické je to pořád ještě nepoužitelné. Nicméně jak nám řikali někdy na vejšce, je třebas po tomhle důkazu od této funkce pomalu ustupovat. Microsoft to hodlá udělat v 2017.
  • SHA256, SHA384, SHA512 – 256, 385, 512 bitů. Tyto hashe ještě nebyly žádným způsobem nabořeny takže “clear” i pro tu největší bezpečnost. Pochopitelně to něco stojí, o proti SHA1 je to cca 20-25% výkonu (podle wiki, vnitřní implementaci Oracle jsem neměřil)
  • MD5 - 128bitů. Kryptograficky i uživatelsky prolomená z pohledu kolizí. Kolize jsme schopni hledat skoro v runtime pro libovolný vstup. Není to tak dlouho, co to bylo dokázáno a konkrétně za tím stál čech pracující na MatFyzu – Vlastimil Klíma a pokud si dobře pamatuju, tak paralelně s ním bořil MD5 tým Wangové v Číně, ale to neni tak podstatné – nebyli první a Wang se jmenuje půlka Číny ;) Určitě se hodí pro výpočty, kde nám nejde úplně o bezpečnost, patrně to bude sprinter (podle wiki až dvakrát rychlejší než SHA*)

Oracle pochopitelně nepřišel s HASHema až nyní, ale byly k dispozici již dříve – ale pouze jako procedury v PL/SQL balících DBMS_CRYPTO a DBMS_OBFUSCATION_TOOLIKIT. V SQL byla pouze silně kolizní ORA_HASH (32bit). Takže nyní plně v “pure” SQL pomocí funkce STANDARD_HASH (a opět chybí sůl). Příkla z duálu:

select
standard_hash('Budlíky') as default_sha1,
standard_hash('Budlíky','SHA1') as default_explicit_sha1,
standard_hash('Budlíky','MD5') as MD5,
standard_hash('Budlíky','SHA256') as SHA256,
standard_hash('Budlíky','SHA384') as SHA384,
standard_hash('Budlíky','SHA512') as SHA512
from dual;

Výsledek:
Poznámky:

  • Vrací typ RAW
  • Nelze použít na LOBy a LONGy

To by mohlo být vše ;) Ještě link na přednášku Vlastimila Klímy pár měsíců po té, co prolomil md5. Přednášku jsme měli někde na FELu v rámci CryptoFestu : Video z AVC ČVUT.

 Posted by at 23:32
Jan 272014
 

Další (ne)zajímavá novinka z nové verze databáze Temporal Validity. Zkrácenědo tabulky ve které jsou dva datumové sloupce, které pokryvají nějaké časové okno (například sloupce zacatek_platnost, konec_platnost) lze přidat mechanizmus, který zobrazí jen záznamy, které  byly v daný čas validní. Technicky vzato je to úplně stejné, jako napsat do podmínky where (moje_datum > zacatek_platnost and moje_datum < konec_platnost). Ačkoliv je to trošku lež. Oracle při přidání filtru handluje pochopiteně ještě i nully. Tedy  korektně je to tato podmínka: (((zacatek_platnosti is null or zacatek_platnosti <=moje_datum)  and (konec_plastnost is null or konec_platnost>moje_datum))). Ano, takto polouzavřený interval. Takže asi tak ;) A rovnou příklad:

create table tbl_test_temporal_validity
(
id number,
zacatek_platnost date,
konec_platnost date,
period for validni(zacatek_platnost,konec_platnost)
);

A nyní by tam chtělo nasypat nějaká ta data:

insert into tbl_test_temporal_validity select rownum,sysdate-(10-rownum),sysdate+mod(rownum,7) from dual connect by level<11;

Což insertuje nějaká takováto data:

Dnes je 27.1. a  mínus 5 dní je 22.1. takže všechny záznamy, které začínají později (23.1.+) nejsou vyselektovány, za zmíňku stojí ještě 22.1., které tam padlo kvůli časové složce, která na obrázku není vidět, takže to může být matoucí ;) A nyní select s temporal validity:
select * from tbl_test_temporal_validity as of period for validni sysdate-5;

Takže asi tak, nějaké poznámky alespoň:

  • V exekučním plánu se normálně zobrazuje celá podmínka, jako filtr. Tzn. žádná změna o proti selectu s where, jaký by napsal sám programátor
  • V *_tab_cols se sloupec “validni” dá normálně najít a jeho atributy jsou: USER_GENERATED=NO, SEGMENT_COLUMN_ID=null, HIDDEN_COLUMN=yes, VIRTUAL_COLUMN=null, TYP=NUMER
  • Do tabulky jde validni přidat až ex-post, pomocí ALTER TABLE ADD.., sloupce definující časové okno musí v tu dobu existovat.

Lehce užitečné, možná to občas použijeme, ale lidskou samičku to rozhodně neohromí :-(

 Posted by at 05:18
Jan 262014
 

Jednou z novinek 12náctky je i adaptivní exekuční plán – ještěj sem neměl čas se do toho ponořit, ale je to jedna z novinek na kterou jsem se hodně těšil ;). Narazil jsem náhodou na video, jehož spoluautorem je Tomas Kyte, a které to velice pěkně ukazuje. Určitě stojí za to si to vyzkoušet sám, ale video je opravdu kvalitní, těch 6 minut času za to stojí, so enjoy:

 Posted by at 03:57
Jan 262014
 

Dlouho jsem tu neukázal nějakou novinku a sám si ani nehrál – když pominu zklamání z novinky, která slibovala více indexů nad stejným setem sloupců. Přiznám se, že se mi moc nelíbí :/. Před vydáním v novinkách Oracle sliboval možnost více indexů nad stejnými sloupci, pokud budou mít jiné attributy – nedávno jsem koukal na implementaci a jiné atributy jsou chápány jako – jiný typ bitmap/b*tree, jiné partišnování, a unikátní/neunikátní. Čekal jsem víc – jako, že bude stačit, když se budou lišit tablespacem, kaluzulí paralllel apod. Navíc visible může být jen jeden (čekal jsem, že CBO si bude on-line vybírat lepší). Takže nakonec – seriously – nic moc.

Ale to byla jen taková stížnost. Dnes zařazuji do novinek něco, čemu Oracle řiká WHITE LIST, ale v manuálu je lepší hladat ACCESSIBLE BY klauzule.

O co jde? Určitě jste někdy pracovali na systému, který je otevřený a semtam je třeba opravit data, něco naspouštět, něco ohnout. Čapnout nějký kus kódu do clipboardu, hodit to žábě nebo (PL/)*SQL Developeru a spustit to. Nebo prostě spustit nějakou funkci z ruky. A nikdo z nás není neomylný, takže kdybych měl udělat top-list chyb bylo by to něco jako:

  • Špatně zadané parametry
  • Špatný čas (pitomý lock), neodhadnutí performace atd.
  • Špatné schéma

A jedna z typicky dalších chyb je, že programátor něco pustí a už nepustí nějakou další část, která je z buisness logiky důležitá. Spustíte proceduru, která sype data do tabulky a neuvědomíte si, že večer předtím běží job, který nad to tabulkou zakládá partitions. Spustíte procku na úpravu objednávky a neuvědomíte si, že když to spuští orgininál aplikace, že to někam loguje atd..

Oracle ACCESSIBLE BY klauzule umožňující nadefinovat procky/funkce/triggery/typy pouze ze kterých je možné daný kód pustit. Takže příklad, mějme funkci, která dejmetomu upravuje zákazníka:

create or replace procedure prc_print_ha accessible by (prc_call_with_log)
as
begin
dbms_output.put_line('Zde by se upravoval zákazník');
end;

Co je nového je červeně označená nová klauzule accessible by, která říká že jediný, kdo může vyvolat funkci prc_print_ha je prc_call_with_log (pro takovéto syntax clarity před to je vhodné napsat slovo procedure, aby bylo na první pohled vidět).  Takže když vyvolám z ruky (ve stejném schématu) samostatnou funkci prc_print_ha:

begin
prc_print_ha;
end;

Tak díky nastavenému white listu jsem vyfuckován:

Error report:
ORA-06550: řádka 2, sloupec 1:
PLS-00904: insufficient privilege to access object PRC_PRINT_HA
ORA-06550: řádka 2, sloupec 1:

Takže následuje založení procedury, která se jmenuje prc_call_with_log.  Ano, můžu založit až ex-post. Když zakládám proceduru/funkci s accessible by kaluzulí, tak nemusí programové jednotky ve white listu ještě existovat a přesto se to správně zkompiluje.

create or replace procedure prc_call_with_log as
begin
dbms_output.put_line('!zde se upravuje zákazník by '||user);
prc_print_ha;
dbms_output.put_line('done');
end;

A pokud nyní zavolám prc_call_with_log, tak jsem v cajku. Prc_call_with_log má právo volat prc_pring_ha a tedy výsledek na output je:

!zde se upravuje zákazník by AZOR
Zde by se upravoval zákazník
done

A tedy není žádná možnost upravit zákazníka (Zde by se upravoval zákazník) aniž bych to nezalogoval (!zde se upravuje zákazník by AZOR; done). Moc šikovná věcička! Která doufám, že bude hojně využivána. Těch chyb vzniklých spuštěním pouze části kódu aplikace z ruky už jsem viděl dost ;) Co k tomu říct? Je možné v accessible by vyjmenovat i procedury/funkce/triggery/typy/package z jiného schématu, pak je třebas schéma explicitně uvéct, něco jako accessible by (procedure azor3.haf, package uservasik.pck_metal). Co je ještě zajímavé je, že to vyfuckuje i SYSa – ani SYS nemá tu sílu pustit funkci s white listem jinak než přes vyjmenované jednotky ve white listu (a pochopitelně případný alter programové jednotky a změnu white listu).

 Posted by at 03:27

Protected: Cíle na rok 2014

 Novinky  Enter your password to view comments.
Dec 242013
 

This content is password protected. To view it please enter your password below:

 Posted by at 08:25
Nov 142013
 

Novinka, tentokrát z pohledu bezpečnosti (Oracle Advanced Security Guide). Od Oracle 12c je tu Oracle Data Redaction, něco co bychom v češtině mohli nazvat maskováním. Hodnoty, které vrátí select lze změnit například na hvězdičky nebo třebas nezobrazit poslední 4 čísla u rodného čísla. Data Redaction Policy se aplikuje online při dotazování a k dispozici je i možnost filtrovat na základě SYS_CONTEXT hodnot. K tomu všemu slouží nový package DBMS_REDACT.

Existuje celkem 5 různých variant:

  • FULL REDACTION – všechno je maskováno
  • PARTIAL REDACTION – je maskována pouze část hodnoty sloupce (poslední 4 čísla apod.)
  • REGULAR EXPRESSION - jsou maskovány hodnoty odpovídající regulérnímu výrazu (možné pouze pro text)
  • RANDOM REDACTION – náhodně generované hodnoty (tzn. při každém spuštění jiné)
  • NO REDACTION – bez maskování, určeno pro testování apod.

A z manuálu pak pár důležitých poznámek:

  • V balíku DBMS_REDACT jsou k dispozici předefinované typy pro maskování některých hodnot. Pochopitelně americké standardy/formáty čísel (security number, zip code apod.)
  • Data Redaction Policy přeplácne právo EXEMPT REDACTION POLICY, podobně jako je právo EXEMPT ACCESS POLICY pro potlačení VPD
  • Na jednom sloupci může existovat pouze jedna policy

Fajn a hurá do hébičkování, první a nejjednodušší možnost – FULL REDACTION. Nejprve však nějaká tabulka na zkoušku:

CREATE TABLE TEST_REDACTION AS
SELECT ROWNUM AS ID,
DECODE(ROWNUM,1,'Suicide Silence',2,'Beneath the Sky',3,'Bleed From Within'AS BAND,
ROWNUM*MOD(ROWNUM,2)*1000 AS COST
FROM DUAL CONNECT BY LEVEL<5;

Tabulka pro zkoušení data redaction

Tabulka pro zkoušení data redaction

A rovnou na to pověsme Data Redaction Policy:
BEGIN
DBMS_REDACT.ADD_POLICY (
object_schema=>'AZOR',
object_name=>'TEST_REDACTION',
policy_name=>'REDACTION_POLICY_2',
column_name=>'BAND',
function_type=>DBMS_REDACT.FULL,
expression=>'1=1',
enable=>TRUE,
policy_description=>'First test Data Redaction',
column_description=>'BAND COLUMN');
END;

S tím, že parametry jsou následující:

  • object_schema – místo, kde je umístěn objekt, by default null = aktuální schéma
  • object_name - jméno tabulku nad kterou chceme data redaction policy navěsit
  • policy_name - jméno data redaction policy
  • column_name – název sloupce, pro který bude tato funkce aplikována
  • fuction_type – typ data redaction policy – NONE, FULL, PARTIAL, RANDOM, REGEXP
  • expression - výraz/filtr pro které řádky se má funkce aplikovat – 1=1 je pro všechny, může však být něco složitějšího, včetně odkaz na SYS_CONTEXT
  • enable - aktivní/neaktivní, by default data redaction policy je zapnutá
  • policy_description,column_description – prostě popis pro dokumentaci a tak.

Podívejme se jak vypadá select z tabulky po přidání Oracle Data Redaction:

Data Redaction - příklad 1

Data Redaction - příklad 1

Výborný, hodnoty byly vymaskovány, done. Původně jsem zde chtěl zkusit všechny typy Oracle Data Redaction, ale to asi není tak zajímavé, jako když sejdu z cesty a povedu tento příspěvek jinou cestou. Pochopitelně mi zajímalo jak je to s vymaskovanými hodnoty a s joiny, where apod. Takže jsem zkusil následující:

Oracle Data Redaction vs. where podmínka

Oracle Data Redaction vs. where podmínka

Tzn, když se odkážeme na konkrétní hodnotu ve sloupci, můžeme podle ní filtrovat. Což je na jednu stranu fajn, na stranu druhou, ale v tomhle konkrétním případě dokážu zjistit jaká hodnota ve sloupci je, použiji-li hrubou sílu. Takže pojďme raději zkoumat tohle ;)

Insertněme nějaký řádek do tabulky a naší snahou pak bude zjistit hodnotu ve sloupci BAND:

INSERT INTO TEST_REDACTION VALUES(5,
CHR(DBMS_RANDOM.VALUE(65,90)) ||
CHR(DBMS_RANDOM.VALUE(65,90)) ||
CHR(DBMS_RANDOM.VALUE(65,90)) ||
CHR(DBMS_RANDOM.VALUE(65,90)) ||
CHR(DBMS_RANDOM.VALUE(65,90))
,99);
commit;

CHR(DBMS_RANDOM.VALUE(65,90)) – náhodné číslo od 65 do 90 (čísla ASCII pro velká písmena) a z toho CHR a to všechno 5x za sebou – tedy ve sloupci BAND je 5 náhodných velkých písmen. ID řádku je 5 a sloupec COST má hodnotu 99. Sloupec COST doufám, že nemate, chtěl jsem ho pojmenovat jako případně sloupec, který by jménem mohl být kandidátem pro maskování a jako jelito mi nenapadlo, že by se to mohlo pléct s COSTem optimalizátoru se kterým to nesouvisí, což je doufám vidět.

Takže select tohoto řádku:

Oracle Data Redaction - zjištění hodnoty

Oracle Data Redaction - zjištění hodnoty

Ok, řekněme, že máme zjistit hodnotu nějakého sloupce po aplikaci této redakční politiky – a předpokládejme že nás bude zajímat nějaký konkrétní řádek a ROWID bude nezbytné pro ověření, že ještě nečelíme nějakému VPD či nastavení náhodného maskování. A nyní jak na to!

Je k dispozici možnost ptát se na sloupec BAND v klauzuli WHERE. Velká písmena, která jsou ve sloupci jsou na hodnotách ASCII 65 až 90, tedy když rozpůlíme interval možných hodnot :(65+90)/2 je cca 78, což je dle ASCII písmeno ‘N’, tedy půlka abecedy. A nyní zjistíme jestli hodnota ve sloupci BAND je větší nebo menší než N, tedy jestli hodnota ve sloupci BAND začíná na A-M nebo na O-Z:

Oracle Data Redaction - získání hodnot I

Oracle Data Redaction - získání hodnot I

Jinými slovy: první písmeno je něco mezi A-M. Nyní by chtělo interval rozpůlit znovu (65+78)/2 cca 72, což je písmeno H a opět spustit select a zjisti pro který z intervalů A-H či H-M  nám databáze vrátí řádek. Pokud si to zkusím, tak to vrací řádek pro menší než <’H’, tedy v první písmeno je něco mezi A-H a takhle bychom mohli pokračovat. Nebo se na to vykašlat a napsat na to script:

DECLARE
lb_found BOOLEAN:=FALSE;
ln_fetch NUMBER;
lc_actual_predicate VARCHAR2(5);
lc_prediacate VARCHAR2(5);
BEGIN
FOR I_OVER_LETTERS IN 1..5 LOOP
FOR J_OVER_ASCII_VALUES IN 65..90 LOOP
select count(1) into ln_fetch from azor.TEST_REDACTION
where rowid='AAAXH2AAGAAAA22AAA' and
band>=lc_actual_predicate ||chr(J_OVER_ASCII_VALUES);
lc_prediacate:=chr(J_OVER_ASCII_VALUES-1);
EXIT WHEN ln_fetch=0;
END LOOP;
lc_actual_predicate:=lc_actual_predicate|| lc_prediacate;
DBMS_OUTPUT.PUT_LINE(lc_actual_predicate);
END LOOP;
END;

Jehož výstupem je u mě slovo ‘DORSE’. Samozřejmě se jedná o hodně hloupě napsaný script, který nedělá ani binární půlení a který počítá s tím, že ve sloupci jsou opravdu jen velká písmena a je jich 5. Na stranu druhou, modifikace a vylepšení a zobecnění je jednoduché. So:

Oracle Data Redaction - získání hodnot I

Oracle Data Redaction - získání hodnot II

Výborný,  nyní pojďme pro mé účty nagrantovat EXEMPT REDACTION POLICY, což nás zbaví Oracle Data Redaction:
grant EXEMPT REDACTION POLICY to AZOR,AZOR3;

A podívejme se, co je opravdu v tabulce:

Oracle Data Redaction - získání hodnot I

Oracle Data Redaction - získání hodnot III

Takže asi tolik k defaultnímu nastavení DMBS_REDACTION.FULL. K ostatním nastavením se snad na blogu ještě dostanu, speciálně nastavení s regulérními výrazy je vcelku zajímavé.

K novému package patří také nová VIEW, kde je možné si Oracle Data Redaction politiku prohlédnout:

  • REDACTION_POLICIES – obecně politika nad tabulkami
  • REDACTION_COLUMNS – konkrétní politika nad sloupci
  • REDACTION_VALUES_FOR_TYPE_FULL – defalutní hodnoty pro FULL maskování, VARCHAR2 se maskuje jako NULL, NUMBER jako 0 atd.

 

 Posted by at 09:42
Nov 122013
 

Po dlouhé době se vracím k Oracle a je na čase zkusit si další novinku, kterou je rozšíření SQL v Oracle 12c o novou klauzuli, která umožní to, co umí LIMIT v MYSQL.

Jednoduchá (ale velice pěkná) záležitost, tedy rovnou syntaxe (vykopírováno z Oracle® Database SQL Language Reference 12c Release 1 (12.1); E17209-14)

Row Limit Clause - Část první

Row Limit Clause

A nyní, k parametrům a jejich chování:

OFFSET
Počet řádků, které se mají přeskočit. Hodnota typu number, kde platí:

  • kladné číslo, udávající počet řádků, které se má přeskočit
  • pokud je číslo větší než počet vrácených řádků, nevrátí select nic
  • pokud to není celé číslo, ale má i desetinou část, Oracle to truncatne
  • pokud je číslo záporné, chová se to jako nula
  • pokud je to NULL, select nevrátí nic

ROW | ROWS
ROWS nebo ROW – klíčové slovo, ROWS nebo ROW – viz. “oracle semantic clarity” přístup.

FETCH FIRST|FETCH NEXT rowcount|percent
Počet řádků nebo počet procent řádků, které má select vrátit, první řádek na OFFSET+1, kde platí

  • pokud je specifikováno záporné číslo, chová se jako nula
  • pokud je specifikován větší počet řádků než select může vrátit – nevadí, jsou vráceny všechny řádky
  • pokud to není celé číslo, Oracle to zase truncatne (pouze v případě řádku, nikoliv v případě %)
  • pokud je uvedeno NULL, select nevrátí nic

ONLY | WITH TIES
ONLY = pouze definovaný počet/procento řádků, WITH TIES = vezme všechny poslední řádky, které mají stejnou hodnotu a to i když překračují definovaný počet/procento řádků

RESTRIKCE

  • nelze použít společně s FOR UPDATE klauzulí
  • nelze použít společně se sekvencí
  • pro materializované view nelze použít při incremental refresh

To by bylo k teorii vše a nyní nějaké ukázky. Nejprve nějaká tabulka, klasika:

CREATE TABLE TBL_TEST_OFFSET AS
SELECT
ROWNUM as ID,
'AAAA' as A_DUMMY,
'BBBB' as B_DUMMY
FROM DUAL
CONNECT BY LEVEL<=10000;

A rovnou úplně nejjednodušší případ pouze klauzule offset:

Příklad offestu 1

Příklad offestu 1

Funguje – bez order by sice není zaručeno pořadí řádků, ale v tomhle případě asi není problém trošku přimhouřit oči a říct, že načtené řádky od ID=11 jsou díky offestu. Exekuční plán sám o sobě není nějak zajímavý – WINDOW (TABLE FULL SCAN) a option NOSORT.

A ještě jeden příklad, tentokrát s exekučním plánem, výsledek je asi jasný :

Příklad offestu 1

Příklad offestu 1

Co je, ale zajímavé – Oracle neodhaduje cardinalitu ani s klauzulí FETCH NEXT. V předchozím případě je cardinalita odhadnuta pouze na základě podmínky WHERE. Vůbec s touhle novinkou v odhadu cardinality nepočitá a to ani když se mu vnutí hint dynamic_sampling.

 Posted by at 14:18