2016年5月28日土曜日

[Oracle]アプリケーションコンテキストの作成

アプリケーションコンテキストにアプリ固有の情報を格納する方法


ネームスペースの作成

create contextを使用して、ネームスペースを作成する。
ネームスペース作成時には、名前と値を管理するためのPL/SQL(プロシージャやパッケージ)をセットで指定する。

※CREATE ANY CONTEXTシステム権限が必要

sample_ctxネームスペースを作成して、名前と値を管理するためのPL/SQLにはsample_ctx_managerを指定。
この時点では、PL/SQLが存在していなくてもOK
create context sample_ctx using sample_ctx_manager;

名前と値のペアを管理するためのPL/SQLの作成

PL/SQLの名前は、create contextを作成した時の名前にする。
dbms_session.set_contextを使ってアプリケーションコンテキストに名前と値のペアを登録できる。
本来は、ログインしたユーザの情報から、DB検索して値の設定をしたりするらしい。
CREATE OR REPLACE PROCEDURE sample_ctx_mgr
IS
BEGIN
  dbms_session.set_context(
      namespace => 'sample_ctx',
      attribute => 'sample_key',
      value     => 'sample_value'
  );
END;

PL/SQLの実行

うえで作成したPL/SQL実行することでアプリケーションコンテキストに値を設定できる。

セキュリティを高めるためには、安易にexecute権限を付与するとかじゃなくってログイントリガーとかで実現するのがよいらしい。

設定された値の確認

session_contextを参照することで値を確認できる。
07:23:44 SQL> r
  1* select * from session_context

NAMESPACE         ATTRIBUTE        VALUE
------------------------------ ------------------------------ ------------------------------
SAMPLE_CTX         SAMPLE_KEY        sample_value

sys_contextを使うと値を抜き出すことができる。
select sys_context('sample_ctx', 'sample_key') from dual;


アプリケーションコンテキストをうまく使うとセキュリティを高めることができるらしい。
(まだ詳しくわかってない。)

2016年5月27日金曜日

[Oracle]DBMS_SPACE.SPACE_USAGEを使ってブロックの使用量を調べる

このPL/SQLを実行すると結果が出力される。

PL/SQL

set serveroutput on
declare
  segment_owner varchar2(30) := '&owner';
  segment_name  varchar2(30) := '&table';
  segment_type  varchar2(30) := 'TABLE';
  unformatted_blocks   number;
  unformatted_bytes    number;
  fs1_blocks           number;
  fs1_bytes            number;
  fs2_blocks           number;
  fs2_bytes            number;
  fs3_blocks           number;
  fs3_bytes            number;
  fs4_blocks           number;
  fs4_bytes            number;
  full_blocks          number;
  full_bytes           number;
begin                  
  DBMS_SPACE.SPACE_USAGE(
    segment_owner,
    segment_name,
    segment_type,
    unformatted_blocks,
    unformatted_bytes,
    fs1_blocks,
    fs1_bytes,
    fs2_blocks,
    fs2_bytes,
    fs3_blocks,
    fs3_bytes,
    fs4_blocks,
    fs4_bytes,
    full_blocks,
    full_bytes
  );

  dbms_output.put_line('空き領域が0-25%   Blocks = ' || rpad(fs1_blocks, 15)  || ' Bytes = ' || fs1_bytes);
  dbms_output.put_line('空き領域が25-50%  Blocks = ' || rpad(fs2_blocks, 15)  || ' Bytes = ' || fs2_bytes);
  dbms_output.put_line('空き領域が50-75%  Blocks = ' || rpad(fs3_blocks, 15)  || ' Bytes = ' || fs3_bytes);
  dbms_output.put_line('空き領域が75-100% Blocks = ' || rpad(fs4_blocks, 15)  || ' Bytes = ' || fs4_bytes);
  dbms_output.put_line('一杯になったもの  Blocks = ' || rpad(full_blocks, 15)  || ' Bytes = ' || full_bytes);

end;

出力例

空き領域が0-25%   Blocks = 0               Bytes = 0
空き領域が25-50%  Blocks = 0               Bytes = 0
空き領域が50-75%  Blocks = 0               Bytes = 0
空き領域が75-100% Blocks = 22              Bytes = 180224
一杯になったもの  Blocks = 286             Bytes = 2342912

deleteでデータを削除した後の出力例

一杯になったBlockが空きが75から100のところに移動している。
deleteなので使用済みのblockはそのままのこっている
空き領域が0-25%   Blocks = 0               Bytes = 0
空き領域が25-50%  Blocks = 0               Bytes = 0
空き領域が50-75%  Blocks = 0               Bytes = 0
空き領域が75-100% Blocks = 308             Bytes = 2523136
一杯になったもの  Blocks = 0               Bytes = 0

truncate後の出力例

HWMがリセットされている。
空き領域が0-25%   Blocks = 0               Bytes = 0
空き領域が25-50%  Blocks = 0               Bytes = 0
空き領域が50-75%  Blocks = 0               Bytes = 0
空き領域が75-100% Blocks = 0               Bytes = 0
一杯になったもの  Blocks = 0               Bytes = 0

2016年5月21日土曜日

[Oracle]セキュアアプリケーションロール

セキュアアプリケーションロールを使うと、ロール作成時に指定したPL/SQLからのみそのロールを有効化することができるようになる。
また、ロールを有効化する直前に、PL/SQLのコード内でセキュリティ要件を満たしているかのチェックができるメリットがある。

セキュアアプリケーションロールの作成

セキュアアプリケーションロールは、ロール作成時にidentified using を付加することで作成できる。
なお、このタイミングでidentified usingに指定したpl/sqlが存在していなくても問題ない。

SQL> create role sample_role identified using hoge.activation_sample_role;

Role created.

ロールを有効化するためのpl/sqlを作成する

このpl/sqlでは、要件を満たす場合にのみdbms_sessionパッケージを使って、先ほど作ったロールを有効化します。
サンプルとして、接続プログラムを表す値が「SQL*Plus」の場合にロールを有効化します。
create or REPLACE PROCEDURE activation_sample_role
authid CURRENT_USER
AS
BEGIN
  if (SYS_CONTEXT('USERENV','MODULE') = 'SQL*Plus') THEN
    DBMS_SESSION.set_role('sample_role');
  END IF;
END;

ロールの付与

hrスキーマのjobsテーブルへの参照権限をロールに付与し、ロールをhogeユーザに付与する。
SQL> grant select on hr.jobs to sample_role;

Grant succeeded.

SQL> grant sample_role to hoge;

Grant succeeded.

ログインしてロールの確認をする


SQL> sho user
USER is "HOGE"

-- ログイン直後のロールの確認
-- sample_roleは付与されていない
SQL> select * from session_roles;

ROLE
--------------------------------------------------------------------------------
RESOURCE

-- ロールに与えているオブジェクト権限で参照できるテーブルへアクセスしてみるがエラーとなる。
SQL> select* from hr.jobs;
select* from hr.jobs
                *
ERROR at line 1:
ORA-00942: table or view does not exist

-- ロール有効化のPL/SQLを実行
SQL> execute activation_sample_role;

PL/SQL procedure successfully completed.

-- ロールの確認
-- 有効になっていることがわかる
SQL> select * from session_roles;

ROLE
--------------------------------------------------------------------------------
SAMPLE_ROLE

-- ロールに値ている権限で参照できるテーブルも見れるようになる。
SQL> select* from hr.jobs;

JOB_ID    JOB_TITLE          MIN_SALARY MAX_SALARY
---------- ----------------------------------- ---------- ----------
AD_PRES    President        20080      40000

2016年5月10日火曜日

[Oracle]ユーザのパスワードを強制的に有効期限切れにする

ユーザのパスワードを有効期限切れにすることで、次回のログイン時にパスワードの変更を強制できるようになる。

パスワードを有効期限切れにするには、alter userを使用するのでALTER USERシステム権限を持っているユーザで行う必要がある。

下のalter userでhrユーザのパスワードを有効期限切れに出来る。
alter user hr password expire;

アカウントの状態確認

dba_usersのaccount_statusカラムを見ることで、ユーザの状態を確認できる。
パスワードを有効期限切れに変更したHRユーザのステータスが、「EXPIRED」になっていることが確認出来る。
  1* select username, account_status from dba_users where username = 'HR'

USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
HR                             EXPIRED

有効期限切れ状態でのログイン

以下のように、パスワードの有効期限切れであることが表示され、パスワードの変更が強制される。
08:16:41 SQL> conn hr/password
ERROR:
ORA-28001: the password has expired


hrに対するパスワードを変更しています。
新規パスワード:
新規パスワードを再入力してください:
パスワードが変更されました。
接続されました。

2016年5月4日水曜日

[Spring Boot]ConfigurationPropertiesなクラスからメタデータを生成してpropertiesファイルで補完を有効にする

カスタムな設定値を定義した場合に、application.propertiesでIDEの補完を有効にする方法。

設定値を受け取るクラスを作成

@ConfigurationPropertiesアノテーションが設定されたクラスを作成します。
このクラスの場合、「sample.name」と「sample.hoge」という設定値を保持します。
@Component
@ConfigurationProperties(prefix = "sample")
public class SampleConfiguration {

    private String name;

    private String hoge;

    // setterとgetterは省略
}

メタ情報を生成するためのライブラリをビルドスクリプトに追加

上で作ったConfigurationPropertiesアノテーションが設定されたクラスから、メタ情報(jsonファイル)を生成するためのライブラリをビルドスクリプトに追加します。

基本的にこのリンク先通りに設定してあげます。configuration-metadata-annotation-processor

Gradleの場合は、以下の様になります。(必要な箇所のみ)
buildscript {
  repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/plugins-release' }
  }
  dependencies {
    classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7'
  }
}

configure(allprojects) {
  apply plugin: 'propdeps'
  apply plugin: 'propdeps-maven'
  apply plugin: 'propdeps-idea'
  apply plugin: 'propdeps-eclipse'
}

dependencies {
  optional "org.springframework.boot:spring-boot-configuration-processor"
}

compileJava.dependsOn(processResources)

IDEの設定でアノテーションプロセッサーを有効にする

IntelliJ IDEAの場合は、設定画面の「Annotation Processors」から有効化します。

プロジェクトをビルドする

プロジェクトをビルドすることでメタデータが生成されるようになります。
今回の場合は、以下のjsonが出力されます。
{
  "groups": [{
    "name": "sample",
    "type": "com.example.SampleConfiguration",
    "sourceType": "com.example.SampleConfiguration"
  }],
  "properties": [
    {
      "name": "sample.hoge",
      "type": "java.lang.String",
      "description": "ほげ",
      "sourceType": "com.example.SampleConfiguration"
    },
    {
      "name": "sample.name",
      "type": "java.lang.String",
      "description": "名前",
      "sourceType": "com.example.SampleConfiguration"
    }
  ],
  "hints": []
}

IDEで使ってみる

この画像のように、メタデータをもとにプロパティとして使えるものがリスト表示されます。