Advanced Cluster Management Updates (Part 1 of 2)
It's been almost a year and half since I did the series on Advanced Cluster Management (ACM). This consisted of four parts
These articles were based on version based on version 2.3.2 of ACM. We are now at ACM 2.6.3. There have been many enhancements which include updates to the GUI/layout, the integration of the multi-cloud console into the main OCP web console (separate route to be deprecated soon), the addition of other cloud providers, more support for Gitops approaches to creating clusters/applications/policies), and (lastly) the addition of the CIM (Central Infrastructure Management/Assisted-Service tooling which allows bare-metal hosts to be discovered and provisioned into clusters.
This article will show two things:
- We already know that applications can be tied to a Github repo based on Channels and Subscriptions, but it hasn't been clear on how to do the same thing with Governance policies. That is to create a GitHub repo (channel) which contains policy (YAML) definitions that can be pulled into ACM.
- In part2 of this series, I wanted to show you how to configure the Central Infrastructure Management/Assisted-Service to handle the discovery and provisioning of bare-metal resources that can eventually be consumed to be part of an OCP cluster. This blog-post outlines how to setup the CIM/Assisted-Service including the bare-metal/cluster YAML definitions. ACM has a GUI that generates these various YAML definitions (infrastructureenvironment, klusterlet, agentclusterinstall, etc) for you. This part will be covered here with a re-hash of some information based on that previous article.
Referencing a GitHub Repo for Governance Policies
One point that was made previously in regards to policies in ACM is that any object definition in Openshift can become a policy to be pushed to other clusters.
In one of the previous articles (part 4 of ACM series), we worked on creating a policy that updated the Oauth configuration to add an htpasswd identity provider. This htpasswd-policy used a secret that created a few users with one of the users given the cluster-admin role.
A similar example will be provided here. I will show the 3 objects that were created to make up this policy (separately). These objects will be put into a policy definition using the PolicyGenerator. Lastly, the policy definition will be put into a GitHub repo which serves as a single-source-of-truth and follows GitOps (Infrastructure as Code) principles.
Just to clarify, these YAML defitions create two users (user1 and user2). Both have passwords of "password". Finally, the user1 is given cluster-admin privileges while user2 remains a regular user.
This code is also provided at the following Github link
OAUTH Configuration
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
annotations:
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
release.openshift.io/create-only: "true"
name: cluster
spec:
identityProviders:
- htpasswd:
fileData:
name: htpasswd-gmszp
mappingMethod: claim
name: htpasswd
type: HTPasswd
HTPASSWD Secret
apiVersion: v1
data:
htpasswd: dXNlcjI6JDJ5JDA1JDRkQ2wvMjVNZG1sSWJvT3FRMGs5cGVMY3pGUElsRFRJQkk0ZWpicmE5MXhpM1FyNWpoNjV1DQp1c2VyMTokMnkkMDUkZE9tV2pkM2lvRFhUMEV5dUNsMW12Li43VnJuTjYwSjJkakYuMDdmTXJkZGo1U1RIZFFlaWENCg==
kind: Secret
metadata:
name: htpasswd-gmszp
namespace: openshift-config
type: Opaque
Linking Cluster-Admin Role to user1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-0
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user1
Now, let's put each of these objects into a single file. This combined file is called htpasswd-combined.yaml located in the same path as the above files. This file has each object separated by ---
In order to generate an ACM Policy, we need to download the kustomize binary and policyGenerator binary. The steps that follow are based on the following article
https://cloud.redhat.com/blog/generating-governance-policies-using-kustomize-and-gitops
- Download kustomize binary
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
This copies the file to your current directory. I recommend copying to /usr/local/bin.
cp kustomize /usr/local/bin
chmod 755 /usr/local/bin/kustomize
2. Make a directory for policyGenerator binary
mkdir -p ${HOME}/.config/kustomize/plugin/policy.open-cluster-management.io/v1/policygenerator
3. Download policyGenerator
curl -L \
-o ${HOME}/.config/kustomize/plugin/policy.open-cluster-management.io/v1/policygenerator/PolicyGenerator \
https://github.com/stolostron/policy-generator-plugin/releases/download/v1.8.0/linux-amd64-PolicyGenerator
4. Change permissions to 755 on file
chmod +x ${HOME}/.config/kustomize/plugin/policy.open-cluster-management.io/v1/policygenerator/PolicyGenerator
Now, we need to create a couple of additional files
The first is kustomization.yaml
generators:
- policy-generator-config.yaml
Next, is policy-generator-config.yaml
apiVersion: policy.open-cluster-management.io/v1
kind: PolicyGenerator
metadata:
name: push-htpasswd-policy
policyDefaults:
namespace: policies
placement:
clusterSelectors:
vendor: "OpenShift"
remediationAction: enforce
policies:
- name: push-htpasswd-policy
manifests:
- path: htpasswd-combined.yaml
This takes the htpasswd-combined YAML file and adds a clusterSelector (vendor: OpenShift) and a remediation action of enforce to the resulting policy.
To build the policy, run the following command. The policy will be output to the screen. You can either redirect to a file or copy/paste from here.
kustomize build --enable-alpha-plugins
This resulting policy has been saved on the Github repo as htpasswd-policy.yaml for reference. This file will be used again in the next part (deploying policy through Github repo)
apiVersion: apps.open-cluster-management.io/v1
kind: PlacementRule
metadata:
name: placement-push-htpasswd-policy
namespace: policies
spec:
clusterConditions:
- status: "True"
type: ManagedClusterConditionAvailable
clusterSelector:
matchExpressions:
- key: vendor
operator: In
values:
- OpenShift
---
apiVersion: policy.open-cluster-management.io/v1
kind: PlacementBinding
metadata:
name: binding-push-htpasswd-policy
namespace: policies
placementRef:
apiGroup: apps.open-cluster-management.io
kind: PlacementRule
name: placement-push-htpasswd-policy
subjects:
- apiGroup: policy.open-cluster-management.io
kind: Policy
name: push-htpasswd-policy
---
apiVersion: policy.open-cluster-management.io/v1
kind: Policy
metadata:
annotations:
policy.open-cluster-management.io/categories: CM Configuration Management
policy.open-cluster-management.io/controls: CM-2 Baseline Configuration
policy.open-cluster-management.io/standards: NIST SP 800-53
name: push-htpasswd-policy
namespace: policies
spec:
disabled: false
policy-templates:
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: push-htpasswd-policy
spec:
object-templates:
- complianceType: musthave
objectDefinition:
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
annotations:
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
release.openshift.io/create-only: "true"
name: cluster
spec:
identityProviders:
- htpasswd:
fileData:
name: htpasswd-gmszp
mappingMethod: claim
name: htpasswd
type: HTPasswd
- complianceType: musthave
objectDefinition:
apiVersion: v1
data:
htpasswd: dXNlcjI6JDJ5JDA1JDRkQ2wvMjVNZG1sSWJvT3FRMGs5cGVMY3pGUElsRFRJQkk0ZWpicmE5MXhpM1FyNWpoNjV1DQp1c2VyMTokMnkkMDUkZE9tV2pkM2lvRFhUMEV5dUNsMW12Li43VnJuTjYwSjJkakYuMDdmTXJkZGo1U1RIZFFlaWENCg==
kind: Secret
metadata:
name: htpasswd-gmszp
namespace: openshift-config
type: Opaque
- complianceType: musthave
objectDefinition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-0
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: user1
remediationAction: enforce
severity: low
I am now going to refernce another Github repository which will be used to hold any ACM policies that I maintain. This repo is located at
The directory structure of this repo has a folder called my-policies with the htpasswd-policy.yaml contained in it
Let's create the channel and subscription which will let us push this policy automatically from ACM. The following steps are based on
- Clone the ACM policy collection GitRepo
git clone https://github.com/stolostron/policy-collection.git
2. Once you clone this repo, CD to policy-collection/deploy directory
cd policy-collection/deploy
3. I am doing all of this as kubeadmin user so I need to create a rolebinding giving kubeadmin subscription-admin privileges
oc adm policy add-cluster-role-to-user open-cluster-management:subscription-admin system:admin
4. Run the following command to deploy the htpasswd policy. This command will push any policy from the my-policies path but this is the only policy currently there.
./deploy.sh -u https://github.com/kcalliga/policy-collection -p my-policies -n policy-namespace -a calligan-policies
Adding the "-a calligan-policies" will make it easier to distinguish the associated channels/subscriptions from others.
4. After running this command, let's return to the ACM GUI and see if the policy has been pushed.
Go to Governance Menu in ACM
See the push-htpasswd-policy has been pushed
I hope you enjoyed this article. The second part of this will be coming soon.