Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜環境導入編〜

# はじめに
2024年1月に、Red Hatは"[Red Hat Developer Hub](https://developers.redhat.com/rhdh)"(以下、**RHDH**)をリリースしました。
RHDHはBackstageをベースとした開発者ポータルであり、サンプルのGolden Pathや、他のRed Hat製品との連携を強化するプラグイン、ならびにエンタープライズレベルのサポートを提供します。

雰囲気を知りたい人は、英語のセッションですが、[YouTube](https://www.youtube.com/watch?v=tvVOC0mFR_4)にデモ動画が上がっていますので一度見てもらうといいかと思います。

ただこういうツールあるあるなのですが、こと使用感やメリットを伝える場合は**環境ありき**なデモになりがちです。ツールの利用者（RHDHでいうと開発者）からすると「おーすげぇ」と感じる一方で、クラスターの運用者、すなわちPlatform Engineerからすると「で、この環境を作るには何をすればいいの？」と思うはずです。少なくとも私はそう思いました。

なので、ここでPlatform Engineer向けにRHDHを導入してサンプルコードを作成し、Golden PathとしてRHDHに登録するところまでの手順をまとめます。

# 実現する環境
今回は以下の環境を構成します。
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/e5c69ce7-0a0a-9d3d-5e72-bc99bae59a0a.png)


# 章項目
今回のテーマは6つの記事で構成されています。
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜環境導入編〜](https://qiita.com/shin7446/items/bafb3619caf5c8ba28c1)  この記事
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜認証設定編〜](https://qiita.com/shin7446/items/b54ebda4ee91ea5f4ca2)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜GitHub Integration編〜](https://qiita.com/shin7446/items/c35010c3ea566beadc5a)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編①〜](https://qiita.com/shin7446/items/ce86d9bbb5121579f9ce)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編②〜](https://qiita.com/shin7446/items/0c181c2f7cc63917bd7c) 
* Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Component UI改善編〜

# 環境導入
本編に入ります。
まず今回の手順を進めるにあたり、以下の環境を前提とします。
## 前提条件
* クラスター環境
    * Red Hat OpenShift on AWS(ROSA): 4.14.6
        * Cluster API Endpoint: Public
* GitHub
    * github.com アカウント1つ
* 作業端末
    * Macbook
        * oc : 4.14.6
            * user-role: cluster-admin
        * vault : v1.14.4
        * helm : v3.13.3

ここではこれらの前提条件を満たすための手順は割愛します。
ちなみにここではROSAを前提としていますが、インターネットに接続可能な環境であればAzure Red Hat OpenShift(ARO)やSelf-ManagedなOpenShiftでも問題ありません。

## 各種ツールのインストール
まずはGolden Pathで利用予定のツールをインストールしていきます。
インストールするツールと、記事で取り扱うバージョンは以下の通りです。
* Via Operator
    * OpenShift Pipelines 1.13.1
    * OpenShift GitOps 1.11.0
    * External Secrets 0.9.11
* Via Helm
    * Hashicorp Vault 1.15.2
    * Sonarqube 9.9.1-community
    * Red hat Developer Hub 1.0

### Red Hat Developer Hub のインストール
まずは今回のメインツールであるRHDHをインストールします。
2024年1月現在では、[公式ドキュメント](https://access.redhat.com/documentation/ja-jp/red_hat_developer_hub/1.0/html/getting_started_with_red_hat_developer_hub/proc-install-rhdh-helm_rhdh-getting-started)にてHelmを使ったインストール方法が記載されています。手順上はOpenShiftのWebコンソールから実行していますが、今後の設定変更・管理を考慮してMacbook上からHelmコマンドを実行します。

まずHelmのリポジトリを取得します。
```
helm repo add openshift-helm-charts https://charts.openshift.io/
```

次にデフォルトの値を取得します。
```
helm show values openshift-helm-charts/redhat-developer-hub > values.yaml
```

ここではインストールに必要な最低限の変更のみ行います。
`values.yaml`内の以下の部分を修正してください。
```values.yaml
# clusterRouteBaseのURLをクラスターのベースドメインに変更
clusterRouterBase: apps.rosa.<cluster_name>.xxxx.xx.openshiftapps.com

# backstageのimageのregistryをquay.ioからregistry.redhat.ioに変更
upstream:
  backstage:
    image:
      registry: registry.redhat.io     ← 変更
      repository: rhdh/rhdh-hub-rhel9
```

Projectを作成し、実際にデプロイしていきます。
```
# Project作成
oc new-project rhdh

# install
helm upgrade -i developer-hub -n rhdh -f values.yaml openshift-helm-charts/redhat-developer-hub
```

しばらくするとPodがrunningになるので、RouteのURLにログインします。
```
oc get route -n rhdh developer-hub -o jsonpath={.status.ingress[0].host}
```

ログイン画面が表示されれば、ひとまずインストール完了です。
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/d0dc22ee-c436-1e08-e454-cb1a31825d4a.png)

### 【Community版 Developer Hub】 Janus のインストール
RHDHは有償のツールのため、すぐには試せない。。。という方は、RHDHのアップストリームである[Janus Project](https://janus-idp.io/)をご利用下さい。こちらはRed Hatによるサポートは受けられませんが、無償で利用できます。開発が活発に行われているため、同様の手順での操作が実現できない可能性がありますが、それを承知の上でこちらをインストールしても、これからの手順は（おそらく）実行できます。

こちらもHelmのリポジトリの取得からはじまります。
```
helm repo add janus-idp https://janus-idp.github.io/helm-backstage
```

次にデフォルトの値を取得します。
```
helm show values janus-idp/backstage > values.yaml
```

`values.yaml`内の以下の部分を修正してください。
```values.yaml
# clusterRouteBaseのURLをクラスターのベースドメインに変更
clusterRouterBase: apps.rosa.<cluster_name>.xxxx.xx.openshiftapps.com

# imageのtagをlatestからnext-1e1e1b0に変更
upstream:
  nameOverride: backstage
  backstage:
    image:
      registry: quay.io
      repository: janus-idp/backstage-showcase
      tag: next-1e1e1b0
```
Projectを作成し、実際にデプロイしていきます。
```
# Project作成
oc new-project rhdh

# install
helm upgrade -i developer-hub -n rhdh -f values.yaml janus-idp/backstage
```

しばらくするとPodがrunningになるので、RouteのURLにログインします。
```
oc get route -n rhdh developer-hub -o jsonpath={.status.ingress[0].host}
```

ログイン画面が表示されれば、ひとまずインストール完了です。
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/2c2a7cba-2925-ff43-b3eb-193c89be8097.png)

---

### OpenShift Pipelines のインストール
PipelinesはOperator Hubからインストールしていきます。
`Operator Hub`で検索バーに`openshift pipelines`と入力して表示されたものを選択します。
![ScreenShot 110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/9d048877-25ea-b88f-2a4a-9a207c88f9af.png)

`インストール`を選択します。
![ScreenShot 111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/bb962eb5-59d4-fdea-0316-613974ce5f8b.png)

全てデフォルトの設定のまま`インストール`を選択します。
![ScreenShot 112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/1d616e09-06f6-f349-2ab9-1c414749b72c.png)

OpenShift Pipelinesはこれでインストール完了です。

---

### OpenShift GitOps のインストール
GitOpsもOperator Hubからインストールします。
`Operator Hub`で検索バーに`openshift gitops`と入力して表示されたものを選択します。
![ScreenShot 107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/99469e1b-4dd3-3db1-2bf6-c0f012db2090.png)

`インストール`を選択します。
![ScreenShot 108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/434d9be3-377a-7dfd-1041-afd2348264b0.png)


全てデフォルトの設定のまま`インストール`を選択します。
![ScreenShot 109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/030e831a-59ed-e9cc-70b5-b0b7014711eb.png)

インストールが完了したら、macのターミナルを開き、ocコマンドで以下を実行します。
```
oc patch argocd openshift-gitops --type=merge -p '{"spec":{"extraConfig":{"application.instanceLabelKey":"argocd.argoproj.io/instance"}}}' -n openshift-gitops
```
これはArgoCDがリソースを追跡する際に必要とするラベル情報を書き換える設定です。詳細は[こちら](https://argocd-operator.readthedocs.io/en/latest/reference/argocd/#application-instance-label-key)。
デフォルト設定ではArgoCDからGitOpsでデプロイされたリソースに対して`app.kubernetes.io/instance`のラベルを自動付与することで追跡を実現しますが、この設定により代わりに`argocd.argoproj.io/instance`のラベルを投入する挙動になります。なぜこの設定を変えるかは後に分かります。

次に、ArgoCDのServiceAccountに対して`cluster-admin`権限を付与しておきます。これはGolden Pathの実行時に様々なリソースをデプロイすることが想定されるためです。
```
oc adm policy add-cluster-role-to-user cluster-admin -z openshift-gitops-argocd-application-controller -n openshift-gitops
```

最後にArgoCDのRouteに対してTLS終端の設定を行います。ROSAであれば、この設定によってArgoCDへの通信を暗号化できます。
```
oc -n openshift-gitops patch argocd/openshift-gitops --type=merge -p='{"spec":{"server":{"route":{"enabled":true,"tls":{"insecureEdgeTerminationPolicy":"Redirect","termination":"reencrypt"}}}}}'
```

OpenShift GitOpsもこれでインストール完了です。

---

### Hashicorp Vaultのインストール
Golden Pathの実行によって環境を払い出すには、**GitOpsによる自動化**が大前提になります。その際に一番の障壁となるのが**Secretの管理**です。
GitにSecretのyamlファイルを置くことは一般的に非推奨となっており、各種パブリッククラウドのシークレート管理サービスやVaultのような独自のシークレットストアを利用することが推奨されます。
今回はROSAなのでAWS Secrets Managerを利用しても良かったのですが、一応AROやSelf-managed OpenShiftでも通用するよう、VaultをOpenShiftクラスター上に構築してこちらをシークレットストアとします。

まずVaultをHelmでインストールしていきます。
```
# Project作成
oc new-project vault

# リポジトリの追加
helm repo add hashicorp https://helm.releases.hashicorp.com

# vaultのインストール
helm upgrade -i -n vault vault hashicorp/vault \
  --set "global.openshift=true" \
  --set "server.dev.enabled=true" \
  --set="injector.enabled=false" \
  --set="server.image.repository=docker.io/hashicorp/vault"
```
* `global.openshift=true`: OpenShiftにVaultをインストールする際に必要なオプションです。
* `server.dev.enabled=true`: VaultをDevelopment modeで起動します。
* `injector.enabled=false`: Vault Sidecarをインジェクトする機能の利用有無を設定します。今回は利用しないのでfalseにします。
* `server.image.repository=docker.io/hashicorp/vault`: vaultのイメージの取得先を設定します。

次にMac上からインストールしたvaultコンテナにアクセスするための設定を行います。
まずはvaultへのアクセス用のRouteを作成します。
```
oc expose svc vault
```
作成したRouteのURLを取得し、環境変数に格納します。
```
export VAULT_ADDR="http://$(oc get route -n vault vault -o jsonpath={.status.ingress[0].host})"
```
vault CLIでログインしてみます。インストール直後のrootユーザーのTokenは`root`となっています。
```
vault login -address=$VAULT_ADDR -method=token token=root
```
```.実行結果
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                  Value
---                  -----
token                root
token_accessor       jTsfDDPkMx5B8Hw0ePkiVyZB
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]
```
これで一応Vaultもインストール完了ですが、今後の利用に向けてもう少し設定を施します。

まず、Vault内のPolicyを作成します。
```
vault policy write read-only - << EOF
path "secret/*" {
  capabilities = ["read"]
}
EOF
```
* ここでは`secret/`配下に格納されているsecretへのread権限を持つ`read-only`というPolicyを作成しています。

次にKubernetesのService AccountからVaultへアクセスできるように、Kubernetesによる認証をオンにします。
```
vault auth enable kubernetes
```

Vault内のRoleを作成します。
```
vault write auth/kubernetes/role/read-only-role bound_service_account_names=default bound_service_account_namespaces=* policies=read-only ttl=60m
```
* ここでは`read-only-role`というRoleに対して、先ほど作成したpolicyをアタッチします。また、"全てのNamespaceのdefault service account"にこのRoleを利用できるようにします。

最後にVaultがKubernetesに接続するための設定を行います。このコマンドはVault Podに直接アクセスして実施します。
```
oc project vault
oc rsh vault-0

vault write auth/kubernetes/config token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt issuer=https://kubernetes.default.svc
```

以上でVaultのインストールと初期設定は完了です。

---

### External Secretsのインストール
VaultにストアしたSecretを、External Secretsを経由して復号します。このExternal SecretsのカスタムリソースのyamlファイルをGitで管理することで、機密情報をGitにアップすることなくSecretの管理を実現します。

External SecretsのインストールもOperatorで行います。
`Operator Hub`で検索バーに`external secrets`と入力して表示されたものを選択します。
![ScreenShot 113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/70531e8a-63ee-2e22-d5b1-b9ae2d8c4736.png)

`続行`を選択します。
![ScreenShot 114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/587844ff-8910-bce6-2bcb-384e1363b73b.png)

`インストール`を選択します。
![ScreenShot 115.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/39eb9fa0-5f7a-dffd-6abc-dab709224b3a.png)

全てデフォルトの設定のまま`インストール`を選択します。
![ScreenShot 116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/1730831a-f271-8c24-8f1a-27d0052ed84b.png)

インストールが完了したら、`OperatorConfig`をデプロイします。
Operatorのタブから`OperatorConfig`を選択し、`OpeartorConfig の作成`を選択します。
![ScreenShot 117.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/0e530197-56f4-d02d-f7ea-61e58d253099.png)

デフォルトの設定のまま`作成`を選択します。
![ScreenShot 118.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/a6e88d8e-2506-bf30-d066-78aefd2f6286.png)

次に`Cluster SecretStore`を作成します。
ここでは設定がいくつか必要のため、yamlファイルを作成してapplyします。
```cluster-secretstore.yaml
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-secretstore
  namespace: external-secrets
spec:
  provider:
    vault:
      server: "http://vault.vault.svc:8200"
      version: v2
      namespace: vault
      auth:
        kubernetes:
          mountPath: kubernetes
          serviceAccountRef:
            name: default
          role: read-only-role
```
* 複数のNamespaceからExternal SecretsにアクセスできるようにClusterワイドなSecretStoreを作成します。
* `auth.kubernetes.role`では先ほどVaultで作成したVault Role`read-only-role`を設定します。
```
# Project作成
oc new-project external-secrets

# yamlのデプロイ
oc apply -f cluster-secretstore.yaml
```
Webコンソール上で問題なく`Cluster SecretStore`がデプロイできているかを確認します。
![ScreenShot 119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/633c43bc-428b-1ea4-ab3a-677b024666a1.png)

これでExternal Secretsもインストール完了です。

---

### Sonarqubeのインストール
最後にSonarqubeをインストールします。SonarqubeはGolden PathでデプロイされるCIパイプライン上でアプリケーションコードのUTに使用します。

SonarqubeはHelmでインストールしますが、公式のHelmチャートではOpenShiftのデフォルトのセキュリティ設定の関係でインストールすることができません。そのためGitHubの[Red Hat Communities of Practice](https://github.com/redhat-cop)にあるhelmチャートを利用します。

```
# Project作成
oc new-project sonarqube

# リポジトリの追加
helm repo add redhat-cop https://redhat-cop.github.io/helm-charts

# sonarqubeのインストール
helm upgrade --install sonarqube redhat-cop/sonarqube -n sonarqube
```

しばらくするとリソースがデプロイされるので、RouteのURLを取得してアクセスします。
```
oc get route -n sonarqube sonarqube -o jsonpath={.status.ingress[0].host}
```


 Sonarqubeのログイン画面が表示されるので`admin/admin`でログインします。
 ![ScreenShot 120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/64f77424-4c08-ab35-70dd-c52a88ab22f6.png)

Passwordをアップデートする必要があるので適当に変更します。

![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/6cc94b2e-b2cd-438a-7c03-94e199abf6b9.png)

Sonarqubeにログインできました。これでいったんSonarqubeのインストールも完了です。
![ScreenShot 121.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/9575b694-f0a5-d8fa-0770-1114057649ac.png)



# おわりに
これでまずはRHDHのインストールと、Golden Pathの実行に必要なツール群のインストールが完了しました。
次の記事ではGolden Pathの実行に向けてRHDHへさまざまな設定を投入したり、必要な認証情報の取得を行なっていきます。