Skip to content

Commit

Permalink
Merge pull request #3 from appuio/initial
Browse files Browse the repository at this point in the history
Add initial version of component
  • Loading branch information
ccremer authored Oct 8, 2021
2 parents d1691df + 2d8f5ba commit 87832b8
Show file tree
Hide file tree
Showing 22 changed files with 443 additions and 5 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,14 @@ jobs:
defaults:
run:
working-directory: ${{ env.COMPONENT_NAME }}
strategy:
matrix:
instance:
- defaults
- empty
steps:
- uses: actions/checkout@v2
with:
path: ${{ env.COMPONENT_NAME }}
- name: Golden diff
run: make golden-diff
run: make golden-diff -e instance=${{ matrix.instance }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ _archive/
_public/

# Additional entries
jsonnetfile.json
4 changes: 4 additions & 0 deletions .sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
docs/antora.yml:
name: group-sync-operator
title: Group Sync Operator

.gitignore:
additionalEntries:
- jsonnetfile.json
8 changes: 8 additions & 0 deletions class/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ parameters:
group_sync_operator:
=_metadata: {}
namespace: syn-group-sync-operator
subscription:
channel: 'alpha'
installPlanApproval: 'Automatic'
name: 'group-sync-operator'
source: 'community-operators'
sourceNamespace: 'openshift-marketplace'
sync: {}
secrets: {}
2 changes: 2 additions & 0 deletions class/group-sync-operator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ parameters:
output_path: apps/
- input_paths:
- group-sync-operator/component/main.jsonnet
- group-sync-operator/component/operator.jsonnet
- group-sync-operator/component/config.jsonnet
input_type: jsonnet
output_path: group-sync-operator/
65 changes: 65 additions & 0 deletions component/config.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
local com = import 'lib/commodore.libjsonnet';
local kap = import 'lib/kapitan.libjsonnet';
local kube = import 'lib/kube.libjsonnet';
local inv = kap.inventory();
// The hiera parameters for the component
local params = inv.parameters.group_sync_operator;

local labels = {
'app.kubernetes.io/managed-by': 'commodore',
'app.kubernetes.io/part-of': 'syn',
'app.kubernetes.io/name': 'group-sync-operator',
};

//
local addCredentialNamespace(config, provider) =
if std.objectHas(config[provider], 'credentialsSecret') then
config {
[provider]+: {
credentialsSecret+: {
namespace: params.namespace,
},
},
}
else
config;

local patchProvider(p) = std.foldl(addCredentialNamespace, std.objectFields(p), com.makeMergeable(p));

local groupSyncs = [
if !std.objectHas(params.sync[k], 'providers') then
error 'GroupSync needs to have at least one provider'
else
{
apiVersion: 'redhatcop.redhat.io/v1alpha1',
kind: 'GroupSync',
metadata: {
name: k,
namespace: params.namespace,
labels+: labels,
},
spec: {
providers: [
{ name: p } + patchProvider(params.sync[k].providers[p])
for p in std.objectFields(params.sync[k].providers)
],
},
}
for k in std.objectFields(params.sync)
];

local credentials = [
kube.Secret(s) {
type: 'Opaque',
metadata+: {
namespace: params.namespace,
labels+: labels,
},
} + com.makeMergeable(params.secrets[s])
for s in std.objectFields(params.secrets)
];

{
[if std.length(groupSyncs) > 0 then '02_groupsync']: groupSyncs,
[if std.length(credentials) > 0 then '02_credentials']: credentials,
}
2 changes: 1 addition & 1 deletion component/main.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ local inv = kap.inventory();
// The hiera parameters for the component
local params = inv.parameters.group_sync_operator;

// Define outputs below
{
'00_namespace': kube.Namespace(params.namespace),
}
43 changes: 43 additions & 0 deletions component/operator.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// main template for group-sync-operator
local kap = import 'lib/kapitan.libjsonnet';
local kube = import 'lib/kube.libjsonnet';
local inv = kap.inventory();
// The hiera parameters for the component
local params = inv.parameters.group_sync_operator;

local operatorgroup = {
apiVersion: 'operators.coreos.com/v1',
kind: 'OperatorGroup',
metadata: {
name: 'group-sync-operator',
},
spec: {
targetNamespaces: [
params.namespace,
],
},
};

local subscription = {
apiVersion: 'operators.coreos.com/v1alpha1',
kind: 'Subscription',
metadata: {
name: 'group-sync-operator',
},
spec: params.subscription,
};

local operator = [
operatorgroup,
subscription,
];

// Define outputs below
{
['01_' + std.asciiLower(obj.kind)]: obj {
metadata+: {
namespace: params.namespace,
},
}
for obj in operator
}
46 changes: 46 additions & 0 deletions docs/modules/ROOT/pages/how-tos/configure-keycloak-sync.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
= Configure Group Sync with Keycloak

To synchronize groups with Keycloak a user with permissions to query for Keycloak groups must be available.
The following permissions must be associated to the user:

* Password must be set (Temporary option unselected) on the Credentials tab
* On the Role Mappings tab, select master-realm or realm-management next to the Client Roles dropdown and then select query-groups, query-users, and view-users.
You should then store the username and password in Vault.

[source,shell]
----
vault kv put -cas=0 clusters/kv/${TENANT_ID}/${CLUSTER_ID}/group-sync-operator/foo/keycloak username=$USERNAME password=$PASSWORD
----

The following is an example of a configuration that will synchronize all groups in realm `foo-public`.
It assumes that the username and password is accessible in Vault at the provided location.

[source,yaml]
----
parameters:
group_sync_operator:
sync:
foo:
schedule: '* * * * *'
providers:
keycloak:
keycloak:
url: https://id.company.io
credentialsSecret:
name: foo-keycloak
loginRealm: master <1>
realm: foo-public
scope: sub <2>
secrets:
foo-keycloak:
stingData:
username: '?{vaultkv:${cluster:tenant}/${cluster:name}/group-sync-operator/foo/keycloak/username}'
password: '?{vaultkv:${cluster:tenant}/${cluster:name}/group-sync-operator/foo/keycloak/password}'
----
<1> The `loginRealm` is the realm where the API user is defined.
<2> Scope for group synchronization.
`sub` will also synchronize subgroups while `one` won't.

NOTE: It's recommended to have the sync user in a separate realm.
90 changes: 89 additions & 1 deletion docs/modules/ROOT/pages/references/parameters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,97 @@ default:: `syn-group-sync-operator`
The namespace in which to deploy this component.


== `subscription`

[horizontal]
type:: dict

The operator subscription details.
The `group-sync-operator` is installed through the OperatorHub.
This field gives you the option to directly modify the operator subscription specification.

== `sync`

[horizontal]
type:: dict
default:: {}

The configuration for group synchronization.
This is a map of group synchronization schedule configurations, which will each be converted to a `GroupSync` object.

== `sync[].schedule`

[horizontal]
type:: string

A crontab based schedule configuration, for when to synchronize the groups.
If no schedule is provided, synchronization will only occur when the `GroupSync` object is reconciled by the platform.


== `sync[].providers`

[horizontal]
type:: dict

Provider configuration for the group synchronization.
Each will be converted to a provider configuration entry in the `GroupSync` resource.
Keys in the dict are used as value for field `name` in the resulting provider configuration.
Consult the https://github.com/redhat-cop/group-sync-operator/#providers[official documentation] on how to configure your provider.

[TIP]
====
For the provider credentials you have the option to create the secret through the `secrets` key.
You can directly reference this secret as a `credentialsSecret` without having to specify the `namespace`.
====


== `secrets`

[horizontal]
type:: dict
default:: {}

Secrets to create in the components namespace.
The dictionary values are directly merged into the `Secret` resource and the Keys in the dict are used as the `name`.


== Example

[source,yaml]
----
namespace: example-namespace
parameters:
group_sync_operator:
sync:
foo:
schedule: '* * * * *'
providers:
keycloak:
keycloak: <1>
url: https://id.company.io
credentialsSecret:
name: foo-keycloak <2>
loginRealm: foo-public
realm: foo-public
scope: sub
bar:
schedule: '* * 2 * *'
providers:
bar-azure:
azure:
credentialsSecret:
name: bar-azure-credentials
secrets:
foo-keycloak: <3>
stingData:
username: foo
password: bar
bar-azure-credentials:
stingData:
AZURE_TENANT_ID: 1a
AZURE_CLIENT_ID: foobar
AZURE_CLIENT_SECRET: secret
----
<1> Configuration according to the https://github.com/redhat-cop/group-sync-operator/#keycloak[official documentation].
<2> References the secret created at (3)
<3> Creates a secret with name `foo-keycloak`
3 changes: 3 additions & 0 deletions docs/modules/ROOT/partials/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
* xref:index.adoc[Home]
* xref:references/parameters.adoc[Parameters]
* xref:how-tos/configure-keycloak-sync.adoc[Configure Group Sync with Keycloak]
42 changes: 40 additions & 2 deletions tests/defaults.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# Overwrite parameters here
parameters:
group_sync_operator:
sync:
foo:
schedule: '* * * * *'
providers:
keycloak:
keycloak:
url: https://id.company.io
credentialsSecret:
name: foo-keycloak
loginRealm: foo-public
realm: foo-public
scope: sub
newProvider:
credentialsSecret:
name: foo-keycloak
credless:
keycloak:
url: https://id.company.io
loginRealm: bar-public
realm: bar-public
scope: sub
other:
schedule: '* * 2 * *'
providers:
foo:
azure:
credentialsSecret:
name: other-foo

# parameters: {...}
secrets:
foo-keycloak:
stingData:
username: foo
password: bar
other-foo:
stingData:
AZURE_TENANT_ID: 1a
AZURE_CLIENT_ID: foobar
AZURE_CLIENT_SECRET: secret
2 changes: 2 additions & 0 deletions tests/empty.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
group_sync_operator: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
annotations: {}
labels:
name: syn-group-sync-operator
name: syn-group-sync-operator
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: group-sync-operator
namespace: syn-group-sync-operator
spec:
targetNamespaces:
- syn-group-sync-operator
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: group-sync-operator
namespace: syn-group-sync-operator
spec:
channel: alpha
installPlanApproval: Automatic
name: group-sync-operator
source: community-operators
sourceNamespace: openshift-marketplace
Loading

0 comments on commit 87832b8

Please sign in to comment.