Pythonのデータ型まとめ

この記事では、Pythonで扱う基本的なデータ型についてまとめてみたいと思います。
Python3系のインタラクティブシェルで各データ型の扱いについて確認していきます。

 

 

文字列型 (str型)

データを文字列として扱うデータ型は「文字列型 (str型)」と呼ばれます。

データを シングルクォーテーション または ダブルクォーテーション で囲む
ことによりコンピュータに文字列型として扱うように伝えることができます。

例として、text という変数に abcde という文字列型のデータを代入する際は
下記のように文字列とするデータをクォーテーションで囲む必要があります。


データ型を確認するには type関数 を使用します。実際にtext変数のデータ型を
確認してみると、下記の通りちゃんと文字列型となっていることが分かります。



ためしにクォーテーションを付けずに変数 text にデータ abcde を代入してみると…


データが not defined (定義されていない) というエラーが出力されてしまいました。
コンピュータには厳密にそのデータが何であるかを伝えないといけないんですね。

 

整数型 (int型)

データを整数列として扱うデータ型は「整数型 (int型)」と呼ばれます。

プログラムに数字をそのまま書いただけのものは整数として認識されます。
ためしに、number という変数に 12345 というデータを代入してみたいと思います。


先程と同様に type関数 を使用してデータ型を確認すると下記の通り、
整数型として扱われていることが確認できました。


では、数字を先程のクォーテーションで囲むとどうなるか確認してみます。


整数型だったデータが文字列型になりました。

下記のように「1」という数列型のデータと「丁目」という文字列型のデータを
足して「1丁目」という文字列を作成したい場合、異なるデータ型同士は足し算
することができないためエラーが出力されてしまいます。


しかし「1」というデータをクォーテーションで囲み文字列型にすることで、
同じデータ型になるため、足し算をして結合することが可能になります。


よって、上記や電話番号等のように数値同士の計算に用いられない
整数については、上記のような文字列型のデータ型の方が適切です。

 

浮動小数点数型 (float型)

長い名前がついていますが、こちらはデータを小数として扱うデータ型になります。
ためしに、number という変数に 123.45 というデータを代入してみたいと思います。


例によって type関数 を使用してデータ型を確認すると下記の通り、
浮動小数点数型として扱われていることが確認できました。


Pythonは電卓のように計算をすることができるのですが、
int型のデータ同士で計算した場合は計算結果もint型で表示されます。


ただし割り算「/」に関しては int型のデータ同士 でも計算結果は float型 になります。


小数点以下を切り捨てた結果を得たい場合は「//」を使用します。

 

複素数型 (complex型)

データを複素数として扱うデータ型は「複素数型 (complex型)」と呼ばれます。

Pythonでは虚数を「j」で表します。
つまり、「jの2乗は-1」になるはずですのでこちらも実際に確認してみます。


確かに-1が出力されました。※虚数部の係数が1であっても省略することはできません

number
という変数に上記を代入して type関数 を使用してデータ型を
確認すると下記の通り複素数型として扱われていることが確認できました。

 

論理型 (bool型)

True」または「False」として扱うデータ型は「論理型 (bool型)」と呼ばれます。
いままでのデータ型とは少し毛色が違う感じがしますね。

比較演算子で数値を比較してみると「True」や「False」といった結果が得られます。


上記は「10より2の方が大きい」という命題が「偽(False)」であるという
結果が出力されている様子です。ためしに、proposition という変数に
上記の命題を代入して type関数 でデータ型を確認してみたいと思います。


たしかに、論理型として扱われていることが確認できました。

 

ここからは、複数のデータを1まとまりに格納できるデータ型たちを確認していきます。

 

リスト型 (list型)

リスト型はまとめたいデータを 大カッコ [ ] の中に カンマ区切り で格納します。
ためしに、fruits という変数に 果物の名前 をリスト型でいくつか入力してみます。


type関数 を使用してデータ型を確認すると下記の通り
リスト型として扱われていることが確認できました。


リスト型は買い物リストのように、項目を追加したり削除したりすることができます。

も食べたくなったのでリストに追加したいと思います。
データを追加する際は appendメソッド を使用します。メソッドを使用する際は
変数 + . + append()」でメソッドのカッコ内に追加したいデータを入力します。


無事にリストに追加されました。

レモンが既に家にあったのでリストから削除したいと思います。
データを削除する際は removeメソッド を使用します。メソッドを使用する際は
変数 + . + remove()」でメソッドのカッコ内に削除したいデータを入力します。


無事にリストから削除されました。

りんごではなく、正確には青りんごが欲しかったのでリストを変更したいと思います。
リストの 0番目にあるapplegreen apple に変更する際は下記のように入力します。


※人間が物を数えるときは1番目、2番目、… と自然数で数えますが、
プログラムでは一番最初を 0番目 から数えます。

 

辞書型 (dict型)

辞書型はまとめたいデータを カッコ { } の中に カンマ区切り で格納します。
見出しとなるキーと対応するデータコロン : でつないでペアにして入力します。

ためしに、fruits_color という変数に 果物の名前と色 を入力してみたいと思います。


type関数 を使用してデータ型を確認すると下記の通り
辞書型として扱われていることが確認できました。


キーを入力すると値を辞書のように引くことができます。
りんごの色を調べてみると下記のように色が出力されます。


下記のように keysメソッドvaluesメソッド を使用して
キーと値を一覧表示することもできます。

 

タプル型 (tuple型)

タプル型はまとめたいデータを カッコ ( ) の中に カンマ区切り で格納します。
fruits 変数に 果物の名前 をタプル型でいくつか入力してみます。


type関数 を使用してデータ型を確認すると下記の通り
タプル型として扱われていることが確認できました。


リスト型と非常に似ていますが、タプル型は immutable であり変更ができません。
りんご青りんごに変更したくてなっても下記のようにエラーが出てしまいます。


また、タプル型はリスト型と違い 辞書型のキー として使用することができます。

たとえば、レモン日付をセットで辞書型のキーとすることができます。
正月三が日に毎日レモンを買った人のキーを作成してみます。


そして、上記のキーを使用してレモンの個数を辞書型のデータで格納してみます。


作成した辞書型のデータ number_of_lemon(レモンの個数) を確認すると
下記の通り、タプル型のデータがキーになっていることが確認できます。


これで、何月何日レモンを何個買ったのかを辞書のように引けるようになりました。

 

集合型 (set型)

集合型はまとめたいデータを カッコ { } の中に カンマ区切り で格納します。
fruits 変数に 果物の名前 を集合型でいくつか入力してみます。


type関数 を使用してデータ型を確認すると下記の通り
辞書型として扱われていることが確認できました。


リスト型のデータを set関数 に渡して集合型のデータに変換することもできます。


集合型のデータに新しいデータを追加する際は updateメソッド を使います。
追加するデータもリスト型で指定する必要があります。


集合型のデータの特徴として、同じデータを持たない というものがあります。
すなわち、データを集合型に変換すれば重複データを削除することができます。

下記のようなリスト型のデータがあったとします。
ぱっとみでもいくつかのデータが重複していますね。


これを  set関数 に渡すと重複が削除されます。


重複が削除された集合型のデータをリスト型に戻すと
最初のリスト型のデータの重複が削除された状態になります。


集合型のデータ同士は文字通り、集合の計算をすることが可能です。
では早速、果物をベン図で分類してみたいと思います。




これを下記の通り集合型のデータでまとめてみました。

 

和集合

黄色い果物 または 緑色の果物」を和集合を使って作成してみます。
和集合は パイプ | または unionメソッド を使用します。


黄色か緑である果物が出力されました。

 

積集合

黄色い果物 かつ 緑色の果物」を積集合を使って作成してみます。
積集合は アンド & または intersectionメソッド を使用します。


黄色も緑もどちらもある果物が出力されました。

 

差集合

黄色い果物 かつ 緑色の果物 以外」を差集合を使って作成してみます。
差集合は マイナス - または differenceメソッド を使用します。


黄色のみの果物が出力されました。

 

排他的論理和集合

黄色い果物 かつ 緑色の果物 以外 または 緑色の果物 かつ 黄色い果物 以外」を
排他的論理和集合を使って作成してみます。排他的論理和集合は キャレット ^
または symmetric_differenceメソッド を使用します。


黄色のみの果物と緑のみの果物が出力されました。

 

黄色い果物 と 緑色の果物 補集合があるのでこちらも確認してみます。

1「黄色い果物 または 緑色の果物 以外


2「黄色い果物 以外 かつ 緑色の果物 以外


3「黄色い果物 かつ 緑色の果物 以外


4「黄色い果物 以外 または 緑色の果物 以外


黄色い果物 と 緑色の果物 補集合である grapepeach が出力されました。

が同じ結果となり、が同じ結果になっています。
(ド・モルガンの法則ですね)

 

以上、Pythonのデータ型についてのまとめでした。

最後までご覧いただきありがとうございました。

 

 

 

 

【Linux】SSH用ユーザを追加する

この記事ではLinuxサーバでSSH接続用ユーザを作成するサーバ側の手順をまとめたいと
思います。下記のようにEC2インスタンス上でLinuxを実行している場合、接続時の認証
に必要となる公開鍵と秘密鍵のキーペアを併せて作成する必要があります。この設定で
秘密鍵を持っている人だけがSSHでログインできる 状態となります。

 

 

 

OS    CentOS Linux release 7.9  

 

ユーザとグループの確認

作成前にユーザとグループを確認しておきたい場合は、下記コマンドを実行します。


■ 現在作成されているユーザを確認

    # cat /etc/passwd          


■ 現在作成されているグループを確認

    # cat /etc/group      



ユーザ作成

早速ユーザを作成していきます。今回はユーザのログインシェルを指定するオプション
とホームディレクトリを指定するオプションを付けて作成コマンドを実行してみます。
作成するユーザ名は testuser で作成してみます。

    # useradd -s /bin/bash -d /home/testuser -m testuser     

 

シェルについては下記にまとめていますのでよろしければご参照ください。

uasdldsau.hatenablog.com

 

ユーザのパスワードを設定

つづいて testuser のユーザのパスワードを設定したいと思います。パスワードを入力
しても画面には何も表示されませんが、これは仕様のため入力に問題はありません。

    # passws testuser     
    Changing password for testuser.
    New password:          ←パスワードを入力
    Retype new password:          ←確認のため再度パスワードを入力
    passwd: all authentication tokens updated successfully.

 

キーペアを生成

つづいて、公開鍵と秘密鍵のキーペアを作成していきます。

 

  1. 作成した testuser にスイッチします。

       # su - testuser     
       # id     


  2. RSAキーペアを作成します。

        # ssh-keygen -t rsa -b 2048     

    OSが Red Hat の場合は、鍵の長さは3072bit以上が推奨のようなので下記で作成します
        # ssh-keygen -t rsa -b 3072 -m PEM     


  3. つづいてキーペアのファイル名とパスフレーズを入力します。

    ファイル名がプロンプトに表示されているデフォルトのファイル名でよい
    場合は「空エンター」を入力して、次のパスフレーズの入力に進みます。

    パスフレーズを入力しても画面には表示されませんがこちらも仕様のため
    入力に問題はありません。秘密鍵を用いてサーバにSSHログインする際は
    ユーザのパスワードではなく、本パスフレーズを入力してログインします。

       Generating public/private rsa key pair.
       Enter file in which to save the key (/home/testuser/.ssh/id_rsa):
          
          
       Created directory '/home/testuser/.ssh'.
       Enter passphrase (empty for no passphrase):       ←パスフレーズを入力
          
          
       Enter same passphrase again:       ←確認のため再度パスフレーズを入力

    余談ですが、秘密鍵を用いずにユーザのパスワードでログインする方法も
    存在します。設定ファイル「/etc/ssh/sshd_config」に記載のパラメータを
    PasswordAuthentication yes」に変更してsshdを再起動することによって
    秘密鍵を用いずに、パスワードだけでログイン可能な設定が反映されます。

    この場合は、秘密鍵パスフレーズではなくユーザのパスワードでログイン
    することになりますが、セキュリティは公開鍵認証方式に比べると劣ります。


  4. 隠しディレクト.ssh に移動します。

       # cd .ssh     
       # pwd     


  5. 公開鍵(id_rsa.pub)を「authorized_keys」に追記します。

    「authorized_keys」は接続を許可する公開鍵を登録するファイルであり
    複数の公開鍵が記述される可能性もあるため、上書きではなく追記にて
    公開鍵を記載していきます。本ファイルを削除するとユーザはサーバに
    ログインすることができなくなります。

       # cat id_rsa.pub >> authorized_keys     


  6. 各種ディレクトリやファイルのパーミッションを変更します。

    .ssh
       # chmod 700 ~/.ssh     

    authorized_keys
       # chmod 644 authorized_keys     

    秘密鍵(id_rsa)
       # chmod 600 id_rsa     


以上でユーザとキーペアの作成は完了です。
作成したユーザにsudo権限を付与する場合は次の手順を実施します。

 

sudo権限の付与

作成した testuser にsudo権限を付与してみたいと思います。

 

  1. sudoersディレクトリに移動します。

       # cd /etc/sudoers.d     


  2. testuser の sudoersファイルを作成します。

    visudoコマンドを使用するとsudoersファイルがロックされることに加えて
    構文チェックも行われるため、安全にファイルを編集することができます。

       # visudo -f /etc/sudoers.d/testuser     


  3. 付与する権限の内容を記載します (今回は全てALLで記述したいと思います)

       testuser ALL=(ALL) ALL


  4. testuser の sudoersファイルが作成されたことを確認します。

       # ls -la /etc/sudoers.d/testuser     
       -r--r-----.  1 root root    24 Aug 13 12:00 testuser     


  5. 動作確認のため testuser にスイッチします。

       # su - testuser     


  6. sudo権限が必要なコマンドを実行してみます。

       # sudo less /var/log/messages     


  7. 3つの格言に目を通した後、記事の冒頭で設定したユーザのパスワードを入力します

       We trust you have received the usual lecture from the local System
       Administrator. It usually boils down to these three things:
    
           #1) Respect the privacy of others.
           #2) Think before you type.
           #3) With great power comes great responsibility.
        
       [sudo] password for testuser:   ←パスワードを入力
    

  8. ログを問題なく閲覧できれば動作確認は完了です。

 

 

以上、SSHユーザ作成とsudo権限付与についてのまとめでした。

最後までご覧いただきありがとうございました。

 

 

 

動的ルーティングを実装する

この記事では動的ルーティングを実現するルーティングプロトコルである
OSPF (Open Shortest Path First) の設定を実施していきます。

ciscoのネットワークシュミレーションツール「Cisco Packet Tracer」を使って
ネットワークの構築をシュミレーションしていきます。ルータやスイッチに
加えてWEBサーバやDNSサーバを設置したり、PCを接続したりすることで
よりインターネットをイメージしやすい構成にしてみたいと思います。

下記のような構成を想定して、ネットワークの構築を行っていきます。
最終的なゴールは全PCからWEBサイトを閲覧できる状態を目指します。


OSPFとは

OSPFは隣接するルータにOSPF Helloパケットを送信することでネイバーを発見します。
OSPFネイバーを発見した後も定期的にOSPF Helloパケットを送信することでネイバーを
維持し続けます。そして各ルータは自らと直接されているルータの情報を保持しており
これを周囲のルータと交換します。このパケットは LSA (Link State Advertisement) と
呼ばれています。

ルータは他のルータからこのLSAを受け取ると、これらの情報を集約している自らの
データベースを更新します。このデータベースは LSDB と呼ばれており、各ルータは
LSAの送受信を繰り返すことでLSDBを同期しています。そしてこのLSDBを基に最適
な経路を導き出しています。

 

 

IPアドレスの決定

それでは早速 各ホスト と 各ルータ のインターフェースのIPアドレスを決めていきます。

このネットワークではクラスCのプライベートIPアドレスである
192.168.1.0/24 ~ 192.168.7.0/24」を使用したいと思います。

「いちくに いちろっぱ」が言いやすく覚えやすいので
このIPアドレスを使って構築していこうと思います。

各インターフェースには下記のようにアドレスを割り振ってみました。

 

 

ホスト部のビットが全て 0 または 1 のアドレスはそれぞれネットワークアドレス
ブロードキャストアドレスであるため機器に割り当てられないため注意が必要です。

 

機器の設置・結線

では機器を設置してみたいと思います。

Cisco Packet Tracer (以下、パケトレ)の下部からアイコンをドラッグアンドドロップして
機器を設置します。ディスプレイネームを構成図通りにリネームして下記の通りに設置が
完了しました。

 

続いて機器同士をケーブルでつないでいきます。

PCルータはポートにMDIポートを使用しており、ハブスイッチはポートに
MDI-Xポートを使用しています。異なるポートはストレートケーブルで接続し、
同じポート同士はクロスケーブルで接続します。

機器の設置と同様にパケトレ下部からアイコンをドラッグアンドドロップして各ポートにケーブルを接続して下記の通りに結線が完了しました。実線がストレートケーブルで破線がクロスケーブルになります。

 

IPアドレスの設定

では先程決定したIPアドレスを機器の各インターフェースに設定していきます。
この構成では、PCやサーバにとってデフォルトゲートウェイは自セグメントの
ルータのインターフェースのIPアドレスになります。

デフォルトゲートウェイを設定しない場合、デフォルトゲートウェイのインターフェースまでは自セグメントであるため通信が届きますが、その先にある他セグメント宛の通信は
どこにルーティングすればよいか示されていない状態のため、破棄されてしまいます。

 

PCとサーバのインターフェース

  1. PC1でインターフェースのIPアドレスデフォルトゲートウェイ
    DNSサーバのIPアドレスを設定します。

     

  2. PC2でインターフェースのIPアドレスデフォルトゲートウェイ
    DNSサーバのIPアドレスを設定します。

     

  3. PC3でインターフェースのIPアドレスデフォルトゲートウェイ
    DNSサーバのIPアドレスを設定します。

     

  4. WEB ServerでインターフェースのIPアドレスデフォルトゲートウェイ
    設定します。

     

  5. DNS ServerでインターフェースのIPアドレスデフォルトゲートウェイ
    設定します。

     

ルータのインターフェース

  1. RT1でインターフェース Gi0/0Gi0/1IPアドレスを設定し有効化します。
    
                 --- System Configuration Dialog ---
    
    Would you like to enter the initial configuration dialog? [yes/no]: no
    
    
    Press RETURN to get started!
    
    
    
    Router>ena
    Router>enable 
    Router#
    Router#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    Router(config)#
    Router(config)#hostn
    Router(config)#hostname RT1
    RT1(config)#
    RT1(config)#
    RT1(config)#inter
    RT1(config)#interface Gi
    RT1(config)#interface GigabitEthernet 0/0
    RT1(config-if)#
    RT1(config-if)#ip add
    RT1(config-if)#ip address 192.168.1.1 255.255.255.0
    RT1(config-if)#
    RT1(config-if)#no shu
    RT1(config-if)#no shutdown 
    
    RT1(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/0, changed state to up
    
    RT1(config-if)#exit
    RT1(config)#
    RT1(config)#
    RT1(config)#
    RT1(config)#
    RT1(config)#
    RT1(config)#inter
    RT1(config)#interface Gi
    RT1(config)#interface GigabitEthernet 0/1
    RT1(config-if)#
    RT1(config-if)#ip add
    RT1(config-if)#ip address 192.168.2.2 255.255.255.0
    RT1(config-if)#
    RT1(config-if)#no shu
    RT1(config-if)#no shutdown 
    
    RT1(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/1, changed state to up
    
    RT1(config-if)#
    RT1(config-if)#
        
  2. RT2でインターフェース Gi0/0Gi0/1 と Gi0/2 IPアドレスを設定し有効化します。
    
             --- System Configuration Dialog ---
    
    Would you like to enter the initial configuration dialog? [yes/no]: n
    
    
    Press RETURN to get started!
    
    
    
    Router>en
    Router>enable 
    Router#
    Router#conf t
    Router#conf terminal 
    Enter configuration commands, one per line.  End with CNTL/Z.
    Router(config)#
    Router(config)#hostn
    Router(config)#hostname RT2
    RT2(config)#
    RT2(config)#
    RT2(config)#inter
    RT2(config)#interface Gi
    RT2(config)#interface GigabitEthernet 0/0
    RT2(config-if)#
    RT2(config-if)#ip add
    % Incomplete command.
    RT2(config-if)#ip add
    RT2(config-if)#ip address 192.168.2.1 255.255.255.0
    RT2(config-if)#
    RT2(config-if)#no shu
    RT2(config-if)#no shutdown 
    
    RT2(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/0, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/0, changed state to up
    
    RT2(config-if)#exit
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#inter
    RT2(config)#interface Gi
    RT2(config)#interface GigabitEthernet 0/1
    RT2(config-if)#
    RT2(config-if)#ip add
    RT2(config-if)#ip address 192.168.3.2 255.255.255.0
    RT2(config-if)#
    RT2(config-if)#no shu
    RT2(config-if)#no shutdown 
    
    RT2(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/1, changed state to up
    
    RT2(config-if)#
    RT2(config-if)#
    RT2(config-if)#exit
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#
    RT2(config)#inter
    RT2(config)#interface Gi
    RT2(config)#interface GigabitEthernet 0/2
    RT2(config-if)#
    RT2(config-if)#ip add
    RT2(config-if)#ip address 192.168.5.4 255.255.255.0
    RT2(config-if)#
    RT2(config-if)#no shu
    RT2(config-if)#no shutdown 
    
    RT2(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/2, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/2, changed state to up
    
    RT2(config-if)#
    RT2(config-if)#
        
  3. RT3でインターフェース Gi0/0Gi0/1 と Gi0/2 IPアドレスを設定し有効化します。
    
             --- System Configuration Dialog ---
    
    Would you like to enter the initial configuration dialog? [yes/no]: no
    
    
    Press RETURN to get started!
    
    
    
    Router>en
    Router>enable 
    Router#
    Router#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    Router(config)#
    Router(config)#host
    Router(config)#hostname R3
    R3(config)#
    R3(config)#
    R3(config)#inter
    R3(config)#interface Gi
    R3(config)#interface GigabitEthernet 0/0
    R3(config-if)#
    R3(config-if)#ip add
    R3(config-if)#ip address 109.168.3.1 255.255.255.0
    R3(config-if)#
    R3(config-if)#no shu
    R3(config-if)#no shutdown 
    
    R3(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/0, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/0, changed state to up
    
    R3(config-if)#exit
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#inter
    R3(config)#interface Gi
    R3(config)#interface GigabitEthernet 0/1
    R3(config-if)#
    R3(config-if)#ip add
    R3(config-if)#ip address 192.168.4.2 255.255.255.0
    R3(config-if)#
    R3(config-if)#no shu
    R3(config-if)#no shutdown 
    
    R3(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/1, changed state to up
    
    R3(config-if)#exit
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#
    R3(config)#inter
    R3(config)#interface Gi
    R3(config)#interface GigabitEthernet 0/2
    R3(config-if)#
    R3(config-if)#ip add
    R3(config-if)#ip address 192.168.6.1 255.255.255.0
    R3(config-if)#
    R3(config-if)#no shu
    R3(config-if)#no shutdown 
    
    R3(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/2, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/2, changed state to up
    
    R3(config-if)#exit
    R3(config)#
    R3(config)#
        
  4. RT4でインターフェース Gi0/0Gi0/1 と Gi0/2 IPアドレスを設定し有効化します。
    
    Press RETURN to get started!
    
    
    
    Router>en
    Router>enable 
    Router#
    Router#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    Router(config)#
    Router(config)#host
    Router(config)#hostname R4
    R4(config)#
    R4(config)#inter
    R4(config)#interface Gi
    R4(config)#interface GigabitEthernet 0/0
    R4(config-if)#
    R4(config-if)#ip add
    R4(config-if)#ip address 192.168.4.1 255.255.255.0
    R4(config-if)#
    R4(config-if)#no shu
    R4(config-if)#no shutdown 
    
    R4(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/0, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/0, changed state to up
    
    R4(config-if)#exit
    R4(config)#
    R4(config)#
    R4(config)#inter
    R4(config)#interface Gi
    R4(config)#interface GigabitEthernet 0/1
    R4(config-if)#
    R4(config-if)#ip add
    R4(config-if)#ip address 192.168.1.2 255.255.255.0
    R4(config-if)#
    R4(config-if)#no shu
    R4(config-if)#no shutdown 
    
    R4(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/1, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/1, changed state to up
    
    R4(config-if)#exit
    R4(config)#
    R4(config)#
    R4(config)#
    R4(config)#
    R4(config)#
    R4(config)#inter
    R4(config)#interface Gi
    R4(config)#interface GigabitEthernet 0/2
    R4(config-if)#
    R4(config-if)#ip add
    R4(config-if)#ip address 192.168.7.1 255.255.255.0
    R4(config-if)#
    R4(config-if)#no shu
    R4(config-if)#no shutdown 
    
    R4(config-if)#
    %LINK-5-CHANGED: Interface GigabitEthernet0/2, changed state to up
    
    %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/2, changed state to up
    
    R4(config-if)#exit
    R4(config)#
    R4(config)#
        

全ての機器のインターフェースにIPアドレスの割り当てが完了すると、
下記のように全てリンクアップした状態になります。

 

ここでルータを確認してみると、この時点では自らが直接接続しているセグメントの
経路しか登録されていないことが分かります。(下記のキャプチャはRT1の設定です)

 

OSPFの設定

いよいよOSPFを設定していきます。networkコマンドではサブネットマスクではなく
ワイルドカードマスクを設定します。また、今回はシングルエリアOSPFを構築したい
のでエリアは全ルータで0を指定します。

 

  1. RT1でOSPFを設定します。
    
    RT1>en
    RT1>enable 
    RT1#
    RT1#
    RT1#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    RT1(config)#
    RT1(config)#router os
    RT1(config)#router ospf 1
    RT1(config-router)#
    RT1(config-router)#netwo
    RT1(config-router)#network 192.168.1.0 0.0.0.255 area 0
    RT1(config-router)#
    RT1(config-router)#network 192.168.2.0 0.0.0.255 area 0
    RT1(config-router)#
    RT1(config-router)#
        
  2. RT2でOSPFを設定します。
    
    RT2>en
    RT2>enable 
    RT2#
    RT2#
    RT2#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    RT2(config)#
    RT2(config)#router os
    RT2(config)#router ospf 1
    RT2(config-router)#
    RT2(config-router)#netw
    RT2(config-router)#network 192.168.2.0 0.0.0.255 area 0
    RT2(config-router)#
    02:33:49: %OSPF-5-ADJCHG: Process 1, Nbr 192.168.2.2 on GigabitEthernet0/0 from LOADING to FULL, Loading Done
    
    RT2(config-router)#
    RT2(config-router)#
    RT2(config-router)#
    RT2(config-router)#
    RT2(config-router)#network 192.168.3.0 0.0.0.255 area 0
    RT2(config-router)# RT2(config-router)#network 192.168.5.0 0.0.0.255 area 0
    RT2(config-router)# RT2(config-router)#
  3. RT3でOSPFを設定します。
    
    R3>en
    R3>enable 
    R3#
    R3#
    R3#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    R3(config)#
    R3(config)#router os
    R3(config)#router ospf 1
    R3(config-router)#
    R3(config-router)#netw
    R3(config-router)#network 192.168.3.0 0.0.0.255 area 0
    R3(config-router)#
    R3(config-router)#network 192.168.4.0 0.0.0.255 area 0
    R3(config-router)# R3(config-router)#network 192.168.6.0 0.0.0.255 area 0
    R3(config-router)# R3(config-router)#
  4. RT4でOSPFを設定します。
    
    R4>en
    R4>enable 
    R4#
    R4#
    R4#conf t
    Enter configuration commands, one per line.  End with CNTL/Z.
    R4(config)#
    R4(config)#router os
    R4(config)#router ospf 1
    R4(config-router)#
    R4(config-router)#netwo
    R4(config-router)#network 192.168.1.0 0.0.0.255 area 0
    R4(config-router)#
    R4(config-router)#network 192.168.4.0 0.0.0.255 area 0
    R4(config-router)#
    R4(config-router)#network 192.168.4.0 0.0.0.255 area 0
    02:27:49: %OSPF-5-ADJCHG: Process 1, Nbr 192.168.2.2 on GigabitEthernet0/1
    
    R4(config-router)# R4(config-router)#network 192.168.7.0 0.0.0.255 area 0
    R4(config-router)# R4(config-router)#

ここでルータを確認してみると、自らが直接接続しているセグメント以外の経路が
OSPFによって登録されていることが分かります。(下記のキャプチャはRT1の設定です)

 

疎通確認

それではネットワークの疎通に問題がないかをpingで確認していきます。
PCとサーバも設置しているため、せっかくなのでエンドツーエンドで
PC1からWEB Serverに向けてpingを打ってみたいと思います。


パケットロスもなく疎通に問題がないことが確認できました!

以上でOSPFの設定は無事に完了したのですが、よりインターネットをイメージしやすく
するためにWEBサーバにコンテンツを作成して、PCのブラウザからURLでアクセスして
サイトを閲覧してみたいと思います。

 

コンテンツの作成

サーバの HTTP から index.html を編集していきます。


せっかくなのでこのブログのブログ名を冠して色味を似せたページを作ってみました。

 

DNSサーバにレコードを登録

WEBサイトにはIPアドレスでもアクセス可能ですが、IPアドレスでアクセスする機会は
ほぼほぼないかと思います。通常はドメイン名を使用してサイトにアクセスしますが、
このドメイン名とIPアドレスを対応付けて管理しているサーバがDNSサーバになります。

今回はドメイン名をWEB ServerのIPv4アドレスと対応させたいのでAレコードを登録
していきます。FQDNもこのブログと同じものを登録してみます。


上記でレコードの登録が完了しました。

 

WEBページにアクセス

それではPCからWEBサイトにアクセスしてみたいと思います。
先程はPC1から疎通を確認しましたので、今回はPC2を使ってみたいと思います。


PC2のデスクトップからWEBブラウザを起動します。


このブログのURLにアクセスしてみます。


先程私がWEB Serverに配置したコンテンツを閲覧することができました!


念のため、本当に名前解決ができているかどうか、
今度はPC3からnslookupコマンドで確認してみます。


問題なく名前解決できていることが確認できました。

 

障害の発生

それでは、このネットワークで障害が発生した場合はどうなるでしょうか。

OSPFはネットワーク構成に変更があった場合でも、変更の差分をネイバールータに
トリガードアップデートするため障害が発生しても自動で最適な経路を再計算します。

こちらも動作を確認してみたいと思います。まず、現状でPC1がWEBサーバに対して
どの経路でアクセスしているかをtracertコマンドを使って確認してみたいと思います。


実行結果から、下記のルートを通っていることが確認できました。


それでは、経路の途中で回線障害が発生したと仮定して、
RT3 - RT4間のケーブルを抜線してみたいと思います。


再度WEBページを確認してみると、抜線したにもかかわらずWEBページが見れています。


障害発生後にどのような経路を通っているか確認してみます。


実行結果から、下記のルートを通っていることが確認できました。
ネットワークトポロジに変更が生じても自動で迂回がかかることが確認できました!

 

以上、OSPFでのネットワーク構築からWEBサイトの閲覧
回線障害が発生した際の動作確認までを実施しました。

最後までご覧いただきありがとうございました。

 

 

 

シェル変数と環境変数の違いとは

この記事では、シェル変数と環境変数の違いと、そもそもシェルとは何なのかについて
調べたことをまとめてみたいと思います。

 

 

シェルとは

コンピュータにはシステム全体を管理するソフトウェアであるOSがあり、そのOSの
中核にはOSの基本機能を担うソフトウェアであるカーネルがあります。しかし人間が
コンピュータを操作するときはカーネル等に直接指示を出すのではなく「シェル」と
呼ばれるソフトウェアを介してカーネル等に指示を出したり出力を受け取ったりします。

シェルはユーザにインターフェースを提供するプログラムであり、カーネルの周りを
まるで卵の殻のように包み込んでるイメージであることからshell(殻)と呼ばれています。

Linuxの場合、具体的にはコマンドラインインターフェースがシェルに該当します。
また、シェルにはいくつもの種類が存在しており、それぞれ様々な特性があります。

サーバにログインし、現在使用しているシェルを確認したい場合は
下記のようにコマンドを実行することで確認することができます。



現在、私はbashシェルを使用しているようです。

bashシェルを介してカーネルに指示を出したり出力を受けとったりしているんですね。他に使用可能なシェルを確認したい場合は下記のようにコマンドを実行することで確認することができます。



 

シェル変数とは

変数は文字列や数値を代入することができるものであり、よく箱などの入れ物に例え
られます。その中でもシェル変数とは「現在実行しているシェルでのみ有効な変数
のことを指します。

現在、私の使用しているbashシェルのシェル変数の値は新しいbashを起動した際や
その他のrbashシェルなどを使用する際には引き継がれないということになります。

実際に検証してみます。

 

  1. まず初めに現在実行しているbashシェルのプロセスIDを確認してみます。
    現在のシェルのプロセスIDは22421のようです。

  2. 続いてここでシェル変数を設定します。「シェル変数=値」で設定できます。

  3.  続いてbashコマンドで新しいbashを起動してみます。

  4.  何も変化がなく不安になりますが、再度bashシェルのプロセスIDを確認してみると現在のシェルのプロセスIDは22431となっており、先程とは別のbashシェルにいることが分かります。

  5. この新しいbashシェルで前のbashシェルで設定したシェル変数を確認すると、何も表示されないことが確認できます。

  6. では新しいbashシェルから抜けてみます。

  7. このままではどこにexitしたか分からないので、再度bashシェルのプロセスIDを確認してみると、プロセスIDは22421となっており最初のbashシェルに戻ってきたことが確認できます。

  8. ここで再度シェル変数を確認してみると問題なく表示されることが確認できます。

たしかにシェル変数は「現在実行しているシェルでのみ有効な変数」であることが確認できました。

ここで、シェルを移動しても同じ変数を使用したいケースが出てくるかと思いますが、
そのようなときに使用するのが「環境変数」です。

 

環境変数とは

環境変数設定が削除されるまでどのシェルでも利用できる変数」です。
シェル変数を export することで環境変数を設定することができます。

こちらも実際に検証してみます。

 

  1. まず初めに現在実行しているbashシェルのプロセスIDを確認してみます。
    現在のシェルのプロセスIDは22444のようです。

  2. 次に現在設定されている環境変数を確認してみます。exportコマンドで確認
    することが可能です。(環境変数が大量に表示されたためgrepで絞っています)

  3. 続いて環境変数を設定していきます。まずシェル変数を設定してからexportコマンドでシェル変数を指定してもよいのですが、シェル変数の設定をexportコマンドで指定することでシェル変数と環境変数を同時に一行で設定することができます。

  4. 再度exportコマンドを実行してみると、環境変数が正常に設定されていることが確認できます。

  5. ではbashコマンドで新しいbashを起動してみます。現在のシェルのプロセスIDは22460となっており、先程とは別のbashシェルにいることが分かります。

  6. ここで先程のシェルで設定した環境変数を確認してみると、新しいbashシェルでも変数を参照できていることが確認できます。

たしかに環境変数は「どのシェルでも利用できる変数」であることが確認できました。


今回はシェルがbashであったため、Bシェル系と呼ばれるシェルの変数の設定方法を
確認してきましたがcshtcshなどのCシェル系のシェルは設定コマンドが異なります。

※しかしながらどちらの系統のシェルであってもシェル変数と環境変数
参照は「set」コマンドを使用し、削除は「unset」コマンドを使用します。

 

変数の削除

先程設定した環境変数を削除してみます。

 

  1. unsetコマンドで$を付けずに変数を指定します。

  2. 変数が削除されたことを確認できました。

 

なお、ログアウトした場合はシェル変数・環境変数ともに上記のように明示的に削除
せずとも変数は消えます。ログアウトしても変数を維持したい場合は、ログイン時に
読み込まれる設定ファイルに設定を記述する必要があります。

 

環境変数の永続化

正確には永続化の設定ではなくログイン時に読み込まれるファイルにて都度
設定しているため永続化しているように見える設定といったものになります。

ログイン時に読み込まれるファイルにはいくつか種類があります。

読み込まれる順番   ファイル 説明
               1 /etc/profile 全ユーザに適用される
               2 ~/.bash_profile    ログイン時に一度だけ読み込まれる       
               3 ~/.bash_login  2のファイルがない場合に読み込まれる 
               4 ~/.profile  3のファイルがない場合に読み込まれる 


そして関連するファイルは他にも様々あります。

ファイル 説明
~/.bashrc bashを起動する都度読み込まれる
~/.bash_logout     ログアウト時に読み込まれる   
/etc/bashrc    /etc/bashrc エイリアスの設定などが記載されている           

 

ここでは1番目に読み込まれる全ユーザに適用される設定ファイルではなく
ユーザのホームディレクトリ配下にあり、2番目に読み込まれる設定である
~/.bash_profile」に環境変数を記述して事実上の永続化を試みてみます。

  1. ホームディレクトリを確認したところ当該ファイルが存在していませんでした。
    (この場合、上記の表の4番目にある .profile が読み込まれることになります)

  2. ~/.bash_profile」ファイルが無かったので作ってしまいます。

  3. ファイルに環境変数を記述します。

  4. 一度ログアウトして再度ログインします。

  5. 環境変数を確認してみると想定通り設定されていることが確認できました。

ログインする度に環境変数が設定されるようになり、これで環境変数の事実上の永続化
を実現することができました。

 

「su -」のハイフンの意味

Linuxサーバにて他のユーザにスイッチする場合は、「su - (他のユーザ名)」のコマンド
を実行することで他のユーザにスイッチすることができます。実はこの「- (ハイフン)」
はsuコマンドのオプションになっており、「シェルをログインシェルにする」といった
意味を持ちます。つまりスイッチした他のユーザのログインシェルでログインするため
他のユーザの環境変数を使用するといった意味になります。

この「- (ハイフン)」はオプションのため、「su (他のユーザ名)」でもスイッチは
可能ですがスイッチ前の現在のユーザの環境変数がスイッチ後も引き継がれます。

では実際に確認してみます。先程上記で設定した testuser の環境変数を引き継がない
ように「su - testuser」ではなく「su testuser」でログインしてみたいと思います。

 

  1. 現在の testuser で先程設定した環境変数を参照できることを確認します。

  2. 次にログアウトして「su testuser」でログインします。

  3. 再度 testuser で先程設定した環境変数を参照するも、testuserのログイン時に
    読み込むファイルを読み込んでいないため、環境変数は表示されませんでした。
    (プロンプトの表示もハイフンオプションを付けたときとは異なっていますね)


このsuコマンドはサーバで設定変更などの重要な作業する際や、障害調査でログを確認
する際などにルートの権限が必要になることで、実行することが多いコマンドかと思い
ますが、この際にルートの環境変数を使用しないと、せっかくルートにスイッチしても
実行できないコマンドが出てくるなどの弊害があるため、suコマンドを実行する際には
ハイフンオプションを付けて実行することがほとんどです。

 

ユーザ変数とシステム変数

ユーザが自身で設定した変数はユーザ変数と呼ばれています。先程から私が設定している
SV=ShellVariable もユーザ変数ということになります。これに対して、システム側で予め
用意されている変数が存在しており、これをシステム変数と呼びます。実は普段何気なく
実行しているコマンドもシステム変数のおかげで何気なく実行することができています。

先程より何度も実行しているechoコマンドを例に確認していきます。echoは「反響」の意
でありechoコマンドは文字列をやまびこのように反響して画面に表示するコマンドです。
echoコマンドを実行するということは、文字列を画面に表示するプログラムを実行する事
を意味しています。

プログラムファイル(コマンドの実体)の在り処はwhichコマンドで調べることができます。


私の環境の場合、echoコマンドの実体はどうやら /bin/echo にあるようです。この
フルパスを指定してechoコマンドを実行しても同じ出力結果を得ることができます。


コマンドを実行する際に実体のプログラムファイルを指定しなくても実行できるのは、
PATHという環境変数が設定されているためです。これはシステム変数の一つであり、
ユーザが作業しやすいようにシステム側であらかじめ設定されているものになります。

それではPATHを確認してみます。


出力結果から分かる通り、echoの実体が置かれている「/bin」だけでなく「/usr/bin」や
「/usr/local/bin」などの複数のディレクトリがコロンで区切られて羅列されています。

Linuxのコマンドは用途に応じて複数の格納場所があり、実行したいコマンドがあるとき、
ユーザがこれらのディレクトリの中から実体を探しだして実行するのはとても大変です。
PATHに格納場所が記述されている場合、コマンドを実行するとコマンドの文字列をPATHに記載されたディレクトリの中から順番に検索して実行するため、ユーザはコマンドの実体の在り処を把握せずともコマンドを実行することができます。
そのためこのパスは「コマンドサーチパス」と呼ばれています。

このPATHにコマンドの格納場所を記述して、コマンドを実行できるようにすることを
パスを通す」と言ったりします。パスが通るとプログラムはシステム側にコマンド
と認識されることになります。逆に格納場所が記述されていないとコマンドの実体を
検索することができないため、コマンドを実行することができません。その場合は
パスを通すか、フルパスでプログラムファイルを指定して実行する必要があります。

先程のsuコマンドでハイフンオプションを付けてルートにスイッチしないと実行できないコマンドが出てくるといった話はここに繋がります。システム変数であるコマンドサーチパスに記載されているディレクトリが、ユーザ毎に異なっている可能性があるからです。

これも実際に確認してみます。

まずはルートのコマンドサーチパスを確認してみます。


続いてtestuserのコマンドサーチパスを確認してみます。


重要な違いとしては、rootには「/sbin」があり testuser にはない点です。「/sbin」は
システム管理用のコマンドやプログラムを置くディレクトリのため、testuserからroot
にsuコマンドでハイフンを付けずに(環境変数を引き継いで)スイッチした場合、rootに
スイッチした意味がなくなってしまいます。


システム変数は PATH(コマンドサーチパス) 以外にもたくさんあります。

▼ ホスト名



▼ ログインユーザ名



▼ カレントディレクトリパス

, etc.

この記事の冒頭で「現在使用しているシェルを確認するコマンド」を実行しましたが、
SHELLもシステムがあらかじめ用意してくれていたシステム変数の1つだったんですね。

 

以上、シェル変数と環境変数についてのまとめでした。

最後までご覧いただきありがとうございました。

 

 

 

【S3】特定のフォルダのみアクセスを許可する

1つのS3バケットに複数のフォルダを作成した場合、特定のフォルダのみアクセス可能な
IAMユーザが必要になるときがあります。この記事では表題の要件を満たすIAMポリシー
と実際の動作について検証した結果を記載します。


S3バケットのフォルダは上記のように作成してみました。今回はfolder1配下の
test1」と「test2」のみアクセスを許可するIAMポリシーを作成してみます。
併せて、特定のIPアドレスからのみ接続できるように制限をかけてみます。

 

IAMポリシーの作成

早速結論ですが、今回の要件を満たすIAMポリシーは下記の通りです。

{
 "Version":"2012-10-17",
 "Statement": [
   {
     "Effect": "Allow",
     "Action": [
         "s3:ListAllMyBuckets"
     ],
     "Condition": {
         "IpAddress": {
             "aws:SourceIp": [
                 "接続元IPアドレス/32"
             ]
         }
     },
     "Resource": [
         "arn:aws:s3:::*"
     ]
   },
   {
     "Effect": "Allow",
     "Action": [
         "s3:ListBucket",
         "GetBucketLocation"
     ],
     "Condition": {
         "IpAddress": {
             "aws:SourceIp": [
                 "接続元IPアドレス/32"
             ]
         },
         "StringEquals": {
             "s3:prefix": [
                 "",
                 "folder1/"
             ]
         }
     },
     "Resource": [
         "arn:aws:s3:::S3バケット名"
     ]
   },
   {
     "Effect": "Allow",
     "Action": [
         "s3:ListBucket",
         "GetBucketLocation"
     ],
     "Condition": {
         "IpAddress": {
             "aws:SourceIp": [
                 "接続元IPアドレス/32"
             ]
         },
         "StringEquals": {
             "s3:prefix": [
                 "",
                 "test1/",
                 "test2/"
             ]
         }
     },
     "Resource": [
         "arn:aws:s3:::S3バケット名/folder1"
     ]
   },
   {
     "Effect": "Allow",
     "Action": [
         "s3:ListBucket",
         "GetBucketLocation"
     ],
     "Condition": {
         "IpAddress": {
             "aws:SourceIp": [
                 "接続元IPアドレス/32"
             ]
         },
         "StringLike": {
             "s3:prefix": [
                 "",
                 "folder1/test1/*",
                 "folder1/test2/*"
             ]
         }
     },
     "Resource": [
         "arn:aws:s3:::S3バケット名"
     ]
   },
   {
     "Effect": "Allow",
     "Action": [
         "s3:*"
     ],
     "Condition": {
         "IpAddress": {
             "aws:SourceIp": [
                 "接続元IPアドレス/32"
             ]
         }
     },
     "Resource": [
         "arn:aws:s3:::S3バケット名/folder1/test1/*",
         "arn:aws:s3:::S3バケット名/folder1/test2/*",
     ]
   }
  ]
}


1つ目のAllowステートメントでは、ユーザ自身のアカウントに存在するS3バケット
一覧表示することを許可しています。

2つ目と3つ目のAllowステートメントでは、フォルダ「folder1」「test1」「test2」を
一覧表示することを許可しています。

4つ目のAllowステートメントでは、フォルダ「test1」「test2」のコンテンツを
一覧表示することを許可しています。

5つ目のAllowステートメントでは、フォルダ「test1」「test2」で全てのS3アクション
(読み取り, 書き込み, 削除など) を実行することを許可しています。

 

動作確認

今回はAWS CLIから接続を確認してみたいと思います。

まずはバケットのフォルダを表示してみたいと思います。

    $ aws s3 ls s3://S3バケット名/
                               PRE folder1
                               PRE folder2

問題なく表示されました。

それではフォルダ「folder1」を表示してみたいと思います。

    $ aws s3 ls s3://S3バケット名/folder1/
                               PRE test1
                               PRE test2
                               PRE test3
    yyyy-mm-dd hh:mm:ss          0                  

こちらも問題なく表示されました。

つづいてフォルダ「folder2」を表示してみたいと思います。

    $ aws s3 ls s3://S3バケット名/folder2/

    An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

こちらは想定通りアクセスできません。

つづいてフォルダfolder1内のtestフォルダをそれぞれ表示してみたいと思います。

    $ aws s3 ls s3://S3バケット名/folder1/test1/
    yyyy-mm-dd hh:mm:ss          0 
    yyyy-mm-dd hh:mm:ss         54 abc.txt
    $ aws s3 ls s3://S3バケット名/folder1/test2/
    yyyy-mm-dd hh:mm:ss          0                  
    $ aws s3 ls s3://S3バケット名/folder1/test3/

    An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied                

こちらも想定通り「test1」と「test2」にアクセスできており、「test3」にはアクセス
できません。※「test1」には事前にテキストファイル「abc.txt」をアップロードして
いたため当該ファイルが表示されています。

それではフォルダfolder1内のオブジェクト「abc.txt」を削除してみたいと思います。

    $ aws s3 rm s3://S3バケット名/folder1/test1/abc.txt
    delete: s3://S3バケット名/folder1/test1/abc.txt          
    $ aws s3 ls s3://S3バケット名/folder1/test1/
    yyyy-mm-dd hh:mm:ss          0 

削除アクションも問題なく実行できることが確認できました。

それでは最後に別の接続元IPアドレスを許可した場合の接続を確認してみます。
IAMポリシーのIPアドレスの記載を変更後にS3バケットを表示してみます。

    $ aws s3 ls s3://S3バケット名/

    An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied                

こちらも想定通りアクセスが拒否されました。
接続元IPアドレス制限もしっかり機能していることが確認できました。

 

以上で特定のフォルダのみアクセスを許可するIAMポリシーの設定は完了になります。

最後までご覧いただきありがとうございました。

 

 

Amazon VPC周りの基本的な設定まとめ

VPC (Amazon Virtual Private Cloud) はその名の通り、AWSに仮想のプライベートなネットワーク領域を作成することができるサービスです。AWSでEC2などのリソースを配置する際の前段階でVPCの作成が必要となります。

VPC作成後にEC2インスタンスを配置して、いざ接続を試みると「インスタンスに接続できない」や「インスタンス間で通信できない」などのトラブルが発生することがありますが、落ち着いてよく見直してみると、VPC周りの設定に不備がある場合が多々あります。

 

そこで、この記事ではVPC周りの基本的な設定である下記についてまとめてみます。

 

VPCの作成

VPCの作成方法を箇条書きにすると下記の通りです。

 

  1. AWSマネジメントコンソールにて VPC を選択
  2. 左ペインから VPC を選択
  3. 右上の VPCを作成 を押下
  4. 名前タグにVPCの名前を入力
  5. IPv4 CIDRに任意の値を入力したい場合は 手動入力 を選択 ※
  6. VPCを作成 を押下

 

※複数のVPCVPCピアリングで接続する場合は、CIDRが重複すると
通信することができなくなりますので注意が必要です。

 

設定した内容を構成図にすると下記の通りです。
この段階ではまだインターネットに接続することはできません。

 

 

サブネットの作成

つづいてVPC内にサブネットを作成します。


サブネットは大きく分けて「パブリックサブネット」と「プライベートサブネット」の2種があります。パブリックサブネットはインターネットから直接接続できるサブネットであり、プライベートサブネットはインターネットから直接接続できないサブネットです。

 

両者の違いは後ほどサブネットに関連付けられるルートテーブルに、インターネットゲートウェイがアタッチされているかどうかの違いだけになります。ルートテーブルにインターネットゲートウェイを割り当てたサブネットはたちまちパブリックサブネットとなり、割り当てていないサブネットはプライベートサブネットになります。

 

インターネットから直接アクセスされるWEBサーバはパブリックサブネットに配置し、インターネットから直接アクセスされないDBサーバはプライベートサブネットに配置するといった下記のパターンがよくある構成になります。セキュリティ上の理由から、DBサーバは極力プライベートサブネットに配置することが望ましいとされています。

 

 

サブネットの作成方法を箇条書きにすると下記の通りです。

 

  1. AWSマネジメントコンソールにて VPC を選択
  2. 左ペインから サブネット を選択
  3. 右上の サブネットを作成 を押下
  4. VPC IDで先程作成したVPCを選択
  5. サブネット名にサブネットの名前を入力
  6. アベイラビリティーゾーンを選択 ※
  7. IPv4 CIDRブロックにサブネットのCIDRを入力
  8. サブネットを作成 を押下

 

アベイラビリティーゾーン(以下、AZ) はデータセンター群の管理単位であり、基本的に各AWSリージョンに2つ以上存在しています。各AZは「ネットワーク設備」「電源装置」「冷却装置」などが完全に独立しており、AZ間は高速な専用線で接続されています。独立した2つ以上のAZが存在していることで、同一リージョン内で冗長構成を取ることが可能になっています。

 

東京リージョンのAZである ap-northeast-1a ap-northeast-1c にパブリックサブネットとプライベートサブネットを1セットずつ作成する場合、サブネットを合計4つ作成することになり、構成図にすると下記のようになります。この段階でもまだインターネットに接続することはできません。

 

 

インターネットゲートウェイの作成

つづいてインターネットとの出入口であるインターネットゲートウェイを作成します。

 

インターネットゲートウェイの作成方法を箇条書きにすると下記の通りです。

 

  1. AWSマネジメントコンソールにて VPC を選択
  2. 左ペインから インターネットゲートウェイ を選択
  3. 右上の インターネットゲートウェイを作成 を押下
  4. インターネットゲートウェイの名前を入力
  5. インターネットゲートウェイを作成 を押下
  6. 一覧から作成したインターネットゲートウェイを選択
  7. 右上の アクション を押下
  8. VPCにアタッチを押下
  9. VPC IDで先程作成したVPCを選択
  10. アタッチ を押下

 

インターネットゲートウェイを作成すると構成図は下記のようになります。
以降のルートテーブルの設定を行うことで通信が可能となります。

 

 

NATゲートウェイの作成

ここでルートテーブルの設定の前に、NATゲートウェイについて見ていきます。

 

プライベートサブネットはインターネットから直接アクセスできない、インターネットゲートウェイのアタッチされていないサブネットですが、プライベートサブネット内にあるサーバでアップデートやソフトウェアをインストールする際にインターネットに出られないのはとても不便です。

 

そこで登場するのがNATゲートウェイです。NATゲートウェイを使用することでプライベートサブネット内から開始した通信はインターネットへ出ることが可能になります。

 

また、NATゲートウェイはAZ内では冗長化されていますが、AZ全体で障害が発生した場合は通信することができなくなりますので、システム全体でNATゲートウェイ冗長化する際はAZごとにNATゲートウェイを作成する必要があります。

※NATゲートウェイのデータ転送はIn/Outの両方で料金が発生するため、
実際に導入する際には費用対効果の点も含めた検討が必要になります。

 

NATゲートウェイの作成方法を箇条書きにすると下記の通りです。
今回はパブリックサブネットにNATゲートウェイを配置してみます。

 

  1. AWSマネジメントコンソールにて VPC を選択
  2. 左ペインから NATゲートウェイ を選択
  3. 右上の NATゲートウェイを作成 を押下
  4. NATゲートウェイの名前を入力
  5. 先程作成したパブリックサブネットを選択
  6. Elastic IPを割り当て
  7. NATゲートウェイを作成 を押下

 

AZごとにNATゲートウェイを作成した場合の構成図は下記の通りです。

 

 

ルートテーブルの設定

つづいて、いよいよルートテーブルを作成します。

 

ルートテーブルも大きく分けて「パブリックルートテーブル」と「プライベートルートテーブル」の2種があります。それぞれ作成すればよいのですが、NATゲートウェイを作成して冗長構成を取っていた場合はAZごとにプライベートルートテーブルを作成する必要があります。ap-northeast-1a のプライベートサブネットの通信は ap-northeast-1a のNATゲートウェイから、ap-northeast-1c のプライベートサブネットの通信は ap-northeast-1c NATゲートウェイからインターネットへと出る必要があります。

 

つまり、構成図では下記のようになり、3つのルートテーブルを作成する必要があります。

 

 

ルートテーブルの作成方法を箇条書きにすると下記の通りです。

 

  1. AWSマネジメントコンソールにて VPC を選択
  2. 左ペインから ルートテーブル を選択
  3. 右上の ルートテーブルを作成 を押下
  4. ルートテーブルの名前を入力
  5. VPC IDで先程作成したVPCを選択
  6. ルートテーブルを作成 を押下

 

つづいてルートテーブルのルートを設定します。

 

  1. 先程作成したルートテーブルを選択
  2. ルート のタブを選択
  3. ルートを編集 を押下
  4. 送信先0.0.0.0/0 を選択
  5. ターゲットにてゲートウェイを選択 ※
  6. プレビュー を押下
  7. 保存 を押下

 

パブリックルートテーブルにはインターネットゲートウェイのルートを、
プライベートルートテーブルにはNATゲートウェイのルートを追加します。
(NATゲートウェイがない場合はプライベートルートテーブルはローカルのみ)

 

つづいてルートテーブルを各々のサブネットに関連付けます。

 

  1. 先程作成したルートテーブルを選択
  2. サブネットの関連付け のタブを選択
  3. サブネットの関連付けを編集 を押下
  4. 上記の構成図の通りにルートテーブルをサブネットに関連付け
  5. 保存 を押下

 

以上の設定を行うと下記の通り、インターネットとの通信が可能な状態になります。

 

 

以上でVPC周りの基本的な設定が完了になります。

最後までご覧いただきありがとうございました。