Skip to content

Latest commit

 

History

History
351 lines (276 loc) · 10.3 KB

intentions.md

File metadata and controls

351 lines (276 loc) · 10.3 KB

Consul Service Mesh

ConsulではService Discovery以外にもService Meshを実現するための様々な機能が用意されています。

  • L7 Traffic Management
  • Security Policies
  • Service Mesh Gateway
  • Proxy
  • Observability

などが代表的な機能です。

Intentionsを使ったSecurity Policy

まずはIntentionsを利用したConsulのFirewall機能を試してみましょう。

アプリのイメージは以下の通りです。

事前準備

GitHubからレポジトリをクローンします。

$ pkill consul
$ cd consul-workshop
$ git clone https://github.com/tkaburagi/consul-intentions-demo

docker-compose.ymlのファイルを見てください。japanapp,corpapp,hashiapp,hashicorpjapanappの四つのアプリが定義されており、それぞれのコンテナにEnvoyがSidecar Proxyとして同居しています。詳しくは説明で補足します。

トラフィックの流れとしては図の通りでjapanappJapanの文字列を返し、corpappjapanappの結果にCorpの文字列をAppendしてCorp Japanを返します。そしてhashiappHashiを返し、hashicorpjapanapphashiappcorpappにリクエストして結果の文字列を連結させHashiCorp Japaをクライアントに返しています。

サイドカーの設定

この流れをまずはSidecar Proxyの設定を作っていきます。

$ cd consul-intentions-demo
$ mkdir consul.d consul_data

この中に4つのファイルを作っていきます。それぞれがサイドカーの設定となります。

sidecar-hashicorpjapanapp.json

cat << EOF > consul.d/sidecar-hashicorpjapanapp.json
{
  "service": {
    "name": "hashicorpjapanapp",
    "address": "10.5.0.3",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 19001,
        "check": {
          "name": "Connect Envoy Sidecar",
          "tcp": "10.5.0.3:19001",
          "interval": "10s"
        },
        "proxy": {
          "upstreams": [
            {
             "destination_name": "hashiapp",
             "local_bind_address": "127.0.0.1",
             "local_bind_port": 5000
           },
            {
             "destination_name": "corpapp",
             "local_bind_address": "127.0.0.1",
             "local_bind_port": 5001
           }
         ]
        }
      }
    }
  }
}
EOF

hashiappcorpappをUpstreamのDestinationとして設定しています。Proxyによりこれらのサービスにリクエストが振られます。

sidecar-hashiapp.json

cat << EOF > consul.d/sidecar-hashiapp.json
{
  "service": {
    "name": "hashiapp",
    "address": "10.5.0.4",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 19001,
        "check": {
          "name": "Connect Envoy Sidecar",
          "tcp": "10.5.0.4:19001",
          "interval": "10s"
        },
        "proxy": {
          "upstreams": [
         ]
        }
      }
    }
  }
}
EOF

hashiappはUpstreamは行いませんのでHealtcheckのみの設定です。

sidecar-corpapp.json

cat << EOF > consul.d/sidecar-corpapp.json
{
  "service": {
    "name": "corpapp",
    "address": "10.5.0.5",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 19001,
        "check": {
          "name": "Connect Envoy Sidecar",
          "tcp": "10.5.0.5:19001",
          "interval": "10s"
        },
        "proxy": {
          "upstreams": [
            {
             "destination_name": "japanapp",
             "local_bind_address": "127.0.0.1",
             "local_bind_port": 5000
           }
         ]
        }
      }
    }
  }
}
EOF

corpappは説明の通りjapanappから文字列を取得するためUpsetreamの設定を行なっています。

sidecar-japanapp.json

cat << EOF > consul.d/sidecar-japanapp.json
{
  "service": {
    "name": "japanapp",
    "address": "10.5.0.6",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 19001,
        "check": {
          "name": "Connect Envoy Sidecar",
          "tcp": "10.5.0.6:19001",
          "interval": "10s"
        },
        "proxy": {
          "upstreams": [
         ]
        }
      }
    }
  }
}
EOF

japanappもUpstream先はありません。サイドカーの設定は以上です。

sidecar-unintentionalapp.json

cat << EOF > consul.d/sidecar-unintentionalapp.json
{
  "service": {
    "name": "unintentionalapp",
    "address": "10.5.0.7",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 19001,
        "check": {
          "name": "Connect Envoy Sidecar",
          "tcp": "10.5.0.7:19001",
          "interval": "10s"
        },
        "proxy": {
          "upstreams": [
            {
             "destination_name": "hashiapp",
             "local_bind_address": "127.0.0.1",
             "local_bind_port": 5000
           },
            {
             "destination_name": "corpapp",
             "local_bind_address": "127.0.0.1",
             "local_bind_port": 5001
           }
         ]
        }
      }
    }
  }
}
EOF

これは実態はhashicorjapanappと同じですが、別のサービスとして扱います。最後に利用するので今は気にしないでください。

アプリのデプロイ

このコンフィグを使ってDockerコンテナを立ち上げてみます。

sudoが必要な方はrun-sudo.shを実行してください。

$ ./run.sh

上で作った各コンフィグレーションはDocker Composeの中で各コンテナにマウントされ、コンフィグとして扱われるように設定されています。

GUIからこのような状態になっていれば起動は成功です。

Docker Composeの起動が完了したら各アプリをテストしてみましょう。

$ curl http://127.0.0.1:3030
Japan

$ curl http://127.0.0.1:2020
Corp Japan

$ curl http://127.0.0.1:1010
Hashi

$ curl http://127.0.0.1:8080
HashiCorp Japan

$ curl http://127.0.0.1:9090
HashiCorp Japan

今の状態だとこのConsul上にある全てのサービスからどのAPIにもAPIにもアクセス出来てしまうためセキュアではありません。通常ファイヤーウォールなどを構築してセキュリティグループを定義していきますが、Consulではサービスベースの制御が可能です。

次にIntentionsを使ってサービスベースでFWを組んでいきます。

Intentionsを使ったアクセス制御

まず全てのサービスをデフォルトでリクエストを受け付けないように設定します。

consul intention create -deny/-allow <SOURCE_SERVICE> <DEST_SERVICE>という形で簡単に定義出来ます。

$ consul intention create -deny '*' hashiapp

この状態だとhashiappにアクセス不可能なため、hashicorpjapanappからリクエストするとエラーになるはずです。

$ curl http://127.0.0.1:8080
{"timestamp":"2019-09-18T06:46:22.716+0000","status":500,"error":"Internal Server Error","message":"I/O error on GET request for \"http://127.0.0.1:5000/\": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server","path":"/"}

一方、corp - japan間にはなんの設定もされていません。

$ curl http://127.0.0.1:2020
Corp Japan

このようにアクセス出来るでしょう。

残りの-denyを設定します。

$ consul intention create -deny '*' corpapp
$ consul intention create -deny '*' japanapp
$ consul intention create -deny '*' hashicorpjapanapp
$ curl http://127.0.0.1:2020
{"timestamp":"2019-09-18T06:50:31.130+0000","status":500,"error":"Internal Server Error","message":"I/O error on GET request for \"http://127.0.0.1:5000/\": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server","path":"/"}%

設定通りエラーとなりました。

次にアプリが正常に動くようAllowの設定します。出来るだけ下記の手順を見ずに図を見ながら設定してみてください。consul intention create -deny/-allow <SOURCE_SERVICE> <DEST_SERVICE>です。

完成形はこのようになります。

$ consul intention create -allow corpapp japanapp
$ consul intention create -allow hashicorpjapanapp corpapp
$ consul intention create -allow hashicorpjapanapp hashiapp

設定が終わったらテストしてみましょう。

$ curl http://127.0.0.1:8080
HashiCorp Japan

きちんとEnd to Endでリクエストが処理されました。最後に意図しないサービスを立ち上げ、そこから各サービスにアクセスが出来ないことを確認します。

unintentionalappにアクセスしてみます。このアプリはアプリの実態とUpstreamの設定はhashicorpjapanappと同じですがIntentionsによりバックエンドのAPIサービスへのアクセスは許可されていません。

9090でアクセスできます。

$ curl http://127.0.0.1:9090
{"timestamp":"2019-09-18T08:50:15.928+0000","status":500,"error":"Internal Server Error","message":"I/O error on GET request for \"http://127.0.0.1:5000/\": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server","path":"/"}

エラーとなり許可しないサービス以外からはアクセスできないことがわかります。

このようにIntentionsを利用するとサービスベースでACLを設定でき、物理的なロケーションのresolveはConsulに任せることができます。

最後にCtr+Cで抜けて全コンテナを停止しておきましょう。

$ docker-compose down

参考リンク