LoginSignup
3
4

More than 3 years have passed since last update.

ICP上でOpenLDAPをPodとして動かして連携させる

Last updated at Posted at 2019-02-17

IBM Cloud Privateでビルトイン管理者ユーザー以外を使用するためには外部にLDAPが必要だが、外部にLDAPサーバーを立てるのではなく、ICPのKubernetesクラスタ内でOpenLDAPをPodとして稼働させてICPのユーザー認証に使用する方法をICP v3.1.2で確認。

Podではなく普通に外部にOpenLDAPを立てる場合は以下が参考になりそう。

使用するHelmチャートについて

この目的で使えるチャートと手順が以下のリポジトリで提供されている。今回はこのチャートを利用する。

このチャートはibm-chartsではなく、あまりメンテナンスされていないようにみえる。phpLDAPadminのPodを一緒にデプロイしてくれたり、初期データをロードする機能もあり、テスト用途としては便利。PersistentVolumeを使っておらず、データは永続化されない。リポジトリのREADMEにもデモ用と記載がある。

ICP用ではなく一般的なOpenLDAPのHelmチャートもあるので、本格的に利用する場合はこちらを利用するべきと思われる。こちらはPersistentVolumeを利用してデータの永続化が可能。どちらもosixia/openldapのDockerイメージを利用している。

OpenLDAPのデプロイ

リポジトリのクローン

リポジトリをクローンする。

コマンド
git clone https://github.com/ibm-cloud-architecture/icp-openldap.git
実行例
$ git clone https://github.com/ibm-cloud-architecture/icp-openldap.git
Cloning into 'icp-openldap'...
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 22 (delta 0), reused 1 (delta 0), pack-reused 20
Unpacking objects: 100% (22/22), done.
$

チャートのアップロード(参考)

チャートをICPに登録する場合は以下の手順で行うが、今回はローカルでチャートを編集する必要があるのでやらない。

チャートをパッケージする。

コマンド
helm package icp-openldap
実行例
$ helm package icp-openldap
Successfully packaged chart and saved it to: /home/sotoiwa/workspace/icp-openldap-0.1.5.tgz
$

ICPにログインする。

cloudctl login \
  -a https://mycluster.icp:8443 \
  --skip-ssl-validation \

Helmチャートをロードする。

コマンド
cloudctl catalog load-helm-chart --archive icp-openldap-0.1.5.tgz
実行例
$ cloudctl catalog load-helm-chart --archive icp-openldap-0.1.5.tgz
Loading helm chart
Loaded helm chart

Synch charts
Synch started
OK
$

ICPコンソールでカタログに追加されたことを確認する。

image.png

イメージのプライベートレジストリへの登録

今回、ICPがオフライン環境にあるため、使用するイメージをICPのプライベートレジストリに登録する。インターネットにつながる環境の場合はこの手順は不要。

ICPはイメージはNamespaceに紐付ける必要があるため、イメージをpushする先のNamespaceを作成する。
GUIでNamespaceを作成する場合はibm-anyuid-hostpath-pspを割り当てること。NamespaceをCLIで作成した場合は、あとでPodSecurityPolicyをバインドするClusterRoleBindingの作成が必要。

kubectl create ns openldap

チャート内のマニフェストを確認し、使用しているイメージをpullしてICPにpushする。busyboxはタグが指定されていなかったが指定するようにした。

docker pull osixia/openldap:1.1.10
docker pull osixia/phpldapadmin:0.7.0
docker pull busybox:1.30.0
docker tag osixia/openldap:1.1.10 mycluster.icp:8500/openldap/openldap:1.1.10
docker tag osixia/phpldapadmin:0.7.0 mycluster.icp:8500/openldap/phpldapadmin:0.7.0
docker tag busybox:1.30.0 mycluster.icp:8500/openldap/busybox:1.30.0
docker push mycluster.icp:8500/openldap/openldap:1.1.10
docker push mycluster.icp:8500/openldap/phpldapadmin:0.7.0
docker push mycluster.icp:8500/openldap/busybox:1.30.0

valuesファイルの作成とチャートの修正

valuesファイルをコピーする。

cp icp-openldap/values.yaml icp-openldap-values.yaml

valuesファイルでイメージのリポジトリとタグをを書き換えるが、マニフェスト・テンプレートにイメージのリポジトリとタグがハードコードされてしまっているので、テンプレート自体も修正が必要。OpenLDAPのイメージ、初期化コンテナとして利用しているbusyboxのイメージ、phpLDAPadminのイメージについて、プライベートレジストリにpushしたイメージと、valuesとテンプレートで指定されているイメージの整合性がとれるようにする。

(追記)プルリクしてマージしてもらったので、マニフェスト・テンプレートの修正は不要でvaluesファイルの修正だけでよいはず。

なお、デフォルトでuser1user4を作るようになっているが必要に応じてユーザーをカスタマイズ可能。管理者のパスワード、ユーザーのパスワードも必要に応じてカスタマイズする。

icp-openldap-values.yaml
OpenLdap:
  Image: "mycluster.icp:8500/openldap/openldap"
  ImageTag: "1.1.10"
  ImagePullPolicy: "Always"
  Component: "openldap"

  Replicas: 1

  Cpu: "512m"
  Memory: "200Mi"

  Domain: "local.io"
  AdminPassword: "admin"
  Https: "false"
  SeedUsers:
    usergroup: "icpusers"
    userlist: "user1,user2,user3,user4"
    initialPassword: "ChangeMe"

PhpLdapAdmin:
  Image: "mycluster.icp:8500/openldap/phpldapadmin"
  ImageTag: "0.7.0"
  ImagePullPolicy: "Always"
  Component: "phpadmin"

  Replicas: 1

  NodePort: 31080

  Cpu: "512m"
  Memory: "200Mi"
templates/openldap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-seedusers
data:
  seedusers.ldif: |
{{- include (print .Template.BasePath "/_seedusers2.ldif.tpl") . | indent 4 }}
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: {{.Release.Name}}
  name: {{.Release.Name}}
spec:
  ports:
    - port: 389
  selector:
    app: {{.Release.Name}}
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{.Release.Name}}
  labels:
    app: {{.Release.Name}}
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: {{.Release.Name}}
    spec:
      initContainers:
        - name: init-copy
          image: mycluster.icp:8500/openldap/busybox:1.30.0
          command: ['sh','-c','cp /config-map/* /config-storage; ls -lrt /config-storage']
          volumeMounts:
          - name: {{.Release.Name}}-seedusers
            mountPath: /config-map
          - name: config-storage
            mountPath: /config-storage
      containers:
        - name: {{.Release.Name}}
          image: {{.Values.OpenLdap.Image}}:{{.Values.OpenLdap.ImageTag}}
          args: ["--loglevel", "debug"]
          volumeMounts:
            - name: config-storage
              mountPath: /container/service/slapd/assets/config/bootstrap/ldif/custom
            - name: ldap-certs
              mountPath: /container/service/slapd/assets/certs
          ports:
            - containerPort: 389
            - containerPort: 636
          env:
            - name: LDAP_LOG_LEVEL
              value: "256"
            - name: LDAP_ORGANISATION
              value: "Example Inc."
            - name: LDAP_DOMAIN
              value: "{{.Values.OpenLdap.Domain}}"
            - name: LDAP_ADMIN_PASSWORD
              value: "{{.Values.OpenLdap.AdminPassword}}"
            - name: LDAP_REMOVE_CONFIG_AFTER_SETUP
              value: "false"
      volumes:
        - name: config-storage
          emptyDir: {}
        - name: ldap-certs
          hostPath:
            path: "/data/ldap/certs"
        - name: {{.Release.Name}}-seedusers
          configMap:
            name: {{.Release.Name}}-seedusers

RoleBindingの作成

ICP v3.1.1以降ではデフォルトではコンテナはrootで起動できないが、OpenLDAPのコンテナはrootで起動する。また、hostPathをマウントする。そのため、rootでの起動が可能でhostPathをマウントできるPodSecurityPolicyを利用可能なClusterRoleを、Podを起動するServiceAccoutにバインドする必要がある
(GUIでNamespaceを作成する場合は、作成時にPodSecurityPolicyを選択すると、自動的にRoleBindingが作成される)。

ICPでは以下の事前定義されたPodSecurityPolicyが存在し、特に指定しなければibm-restricted-pspが利用される。rootで起動し、hostPathをマウントするためibm-anyuid-hostpath-pspを割り当てる。

それぞれのPodSecurityPolicyについては以下のリンク先に説明がある。

$ kubectl get psp
NAME                        PRIV    CAPS                                                                                                                  SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
ibm-anyuid-hostaccess-psp   false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostpath-psp     false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-psp              false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
ibm-privileged-psp          true    *                                                                                                                     RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-restricted-psp          false                                                                                                                         RunAsAny   MustRunAsNonRoot   MustRunAs   MustRunAs   false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
$

ibm-anyuid-pspのPodSecurityPolicyが利用可能なibm-anyuid-clusterroleというClusterRoleが定義されているのでこのClusterRoleを利用する。ちなみに他のibm-privileged-pspなどのPodSecurityPolicyもそれを利用可能なClusterRoleが定義されている。

$ kubectl get clusterrole | grep ibm
ibm-anyuid-clusterrole                                                 5d
ibm-anyuid-hostaccess-clusterrole                                      5d
ibm-anyuid-hostpath-clusterrole                                        5d
ibm-cert-manager-cert-manager                                          5d
ibm-privileged-clusterrole                                             5d
ibm-restricted-clusterrole                                             5d
$

今回openldapというNamespaceにデプロイするので、このNamespaceの全てのServiceAccoutにibm-anyuid-hostpath-clusterroleのClusterRoleをバインドするためのRoleBindingを作成する。

kubectl create rolebinding ibm-anyuid-hostpath-clusterrole-rolebinding \
  --clusterrole=ibm-anyuid-hostpath-clusterrole \
  --group=system:serviceaccounts:openldap \
  -n openldap

チャートのインストール

準備ができたので、チャートをインストールする。

コマンド
helm install --tls --name icp-openldap \
  --namespace openldap \
  -f icp-openldap-values.yaml \
  icp-openldap
実行例
$ helm install --tls --name icp-openldap \
>   --namespace openldap \
>   -f icp-openldap-values.yaml \
>   icp-openldap
NAME:   icp-openldap
LAST DEPLOYED: Sun Feb 17 15:12:54 2019
NAMESPACE: openldap
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME                TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)       AGE
icp-openldap        ClusterIP  10.0.139.191  <none>       389/TCP       0s
icp-openldap-admin  NodePort   10.0.253.179  <none>       80:31080/TCP  0s

==> v1beta1/Deployment
NAME                DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
icp-openldap        1        1        1           0          0s
icp-openldap-admin  1        1        1           0          0s

==> v1/Pod(related)
NAME                                 READY  STATUS             RESTARTS  AGE
icp-openldap-69dcc4d564-zxfcv        0/1    Init:0/1           0         0s
icp-openldap-admin-59547dd5f8-f74d9  0/1    ContainerCreating  0         0s

==> v1/ConfigMap
NAME                    DATA  AGE
icp-openldap-seedusers  1     0s


$

Podが稼働していることを確認する。

$ kubectl get po -n openldap
NAME                                  READY   STATUS    RESTARTS   AGE
icp-openldap-69dcc4d564-zxfcv         1/1     Running   0          51s
icp-openldap-admin-59547dd5f8-f74d9   1/1     Running   0          51s
$

後で使用するのでServiceのIPアドレスを確認する。

$ kubectl get svc -n openldap
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
icp-openldap         ClusterIP   10.0.139.191   <none>        389/TCP        114s
icp-openldap-admin   NodePort    10.0.253.179   <none>        80:31080/TCP   114s
$

ICPコンソールで「管理 > IDおよびアクセス > 認証」からLDAP接続を作成する。

項目 備考
接続名 openldap
サーバー・タイプ カスタム
基本DN dc=local,dc=io
バインドDN cn=admin,dc=local,dc=io
バインドDNパスワード admin
LDAPサーバー ldap://icp-openldap.openldap:389
グループ・フィルター (&(cn=%v)(objectclass=groupOfUniqueNames))
ユーザー・フィルター (&(uid=%v)(objectclass=person)) 事前入力値から変更が必要
グループIDマップ *:cn
ユーザーIDマップ *:uid
グループ・メンバーIDマップ groupOfUniqueNames:uniquemember

image.png

image.png

以上でLDAPの接続は完了。

「管理 > IDおよびアクセス > チーム」からチームを作成し、チームにユーザーまたはグループを追加することでLDAP内のユーザーでもログインできるようなる。

image.png

LDAP側でのユーザーの管理

LDAP側でユーザーを管理するためには、phpLDAPadminが利用できる。NodePort Serviceとして公開されているので、Serviceのポートを確認してアクセスする。

$ kubectl get svc -n openldap
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
icp-openldap         ClusterIP   10.0.139.191   <none>        389/TCP        27m
icp-openldap-admin   NodePort    10.0.253.179   <none>        80:31080/TCP   27m
$

ログインDNはcn=admin,dc=local,dc=io、パスワードはadminでログインする。

image.png

補足

LDAPに接続できなくなるとデフォルトの管理者ユーザーでもログインできなくなる。そのような場合の復旧は以下を参照。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4