Skip to content

Commit

Permalink
feat: IBM Security Verify provider (#328)
Browse files Browse the repository at this point in the history
* compiles

* get access token working

* passing TestGetGroupSuccess

* more tests

* implement Validate()

* passing build

* fixed tests

* syncer impl

* successful build

* feat: ISV provider

* update docs

* update docs

* address feedback

* Undo Docker change

* ci: update Go version

* update workflow version

* revert change

* restore Go version
  • Loading branch information
boonware authored Dec 4, 2024
1 parent 35ee051 commit 488828b
Show file tree
Hide file tree
Showing 13 changed files with 578 additions and 14 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ bin
*.swo
*~
buildtools/yq

# binaries
manager
group-sync-operator

# temporary files
tmp/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.18 as builder
FROM golang:1.21 as builder

WORKDIR /workspace
# Copy the Go Modules manifests
Expand Down
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Integration with external systems is made possible through a set of pluggable ex
* [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
* [Keycloak](https://www.keycloak.org/)/[Red Hat Single Sign On](https://access.redhat.com/products/red-hat-single-sign-on)
* [Okta](https://www.okta.com/)
* [IBM Security Verify](https://docs.verify.ibm.com/verify)
The following sections describe the configuration options available for each provider
Expand Down Expand Up @@ -477,6 +478,54 @@ The secret can be created by executing the following command:
oc create secret generic okta-api-token --from-literal=okta-api-token=<OKTA_API_TOKEN> -n group-sync-operator
```

### IBM Security Verify

Groups defined in [IBM Security Verify](https://help.okta.com/en/prod/Content/Topics/users-groups-profiles/usgp-main.htm) (ISV) can be synchronized into OpenShift. Currently only the `userName` field from ISV will be synchronized. The developer docs for the ISV API can be found [here](https://docs.verify.ibm.com/verify/page/api-documentation).
The following table describes the set of configuration options for the provider:

| Name | Description | Defaults | Required |
| ----- | ---------- | -------- | ----- |
| `credentialsSecret` | Reference to a secret containing authentication details (see below) | `''` | Yes |
| `groups` | List of groups to synchronize (see below) | `nil` | Yes |
| `tenantUrl` | The ISV tenant URL, for example `https://my-isv.verify.ibm.com`) | `''` | Yes |

The following is an example of a minimal configuration that can be applied to integrate with an Okta provider:

```yaml
apiVersion: redhatcop.redhat.io/v1alpha1
kind: GroupSync
metadata:
name: ibmsecurityverify-sync
spec:
providers:
- name: ibmsecurityverify
ibmsecurityverify:
credentialsSecret:
name: isv-group-sync
namespace: group-sync-operator
tenantUrl: https://my-isv.verify.ibm.com
groups:
- name: 'application owners'
id: 645001V3V9
- name: developer
id: 645001V3VA
```

#### Group Objects
Each group object in the `groups` array must contain an `id` field. The group ID can be retrieved by pulling the group information from the ISV API. Optionally, the object may also contain a `name` which corresponds to the group's display name. When defined, the operator will confirm that the name defined in the YAML matches that received from the API when synchronization occurs; as the group IDs are not human-friendly, using the name can confirm the correct groups are configured. If the names do not match an error will be logged.

#### Group Names
The name of each groups created in OpenShift will match the group name in ISV. Any whitespace in the ISV group name will be replaced with a hyphen.

#### Authenticating to IBM Security Verify

A secret must be created in the same namespace as the group-sync-operator pod. It must contain the following keys:

* `clientId` - The API client ID.
* `clientSecret`- The API client secret.

See the IBM Security Verify [API documentation](https://docs.verify.ibm.com/verify/docs/api-access) for setting up authentication.

### Support for Additional Metadata (Beta)

Additional metadata based on Keycloak group are also added to the OpenShift groups as Annotations including:
Expand Down
34 changes: 34 additions & 0 deletions api/v1alpha1/groupsync_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ type ProviderType struct {
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Okta Provider"
// +kubebuilder:validation:Optional
Okta *OktaProvider `json:"okta,omitempty"`

// IbmSecurityVerify represents the IBM Security Verify provider
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="IBM Security Verify"
// +kubebuilder:validation:Optional
IbmSecurityVerify *IbmSecurityVerifyProvider `json:"ibmsecurityverify,omitempty"`
}

// KeycloakProvider represents integration with Keycloak
Expand Down Expand Up @@ -462,6 +467,35 @@ type OktaProvider struct {
Prune bool `json:"prune"`
}

// IbmSecurityVerifyProvider represents integration with IBM Security Verify
// +k8s:openapi-gen=true
type IbmSecurityVerifyProvider struct {
// CredentialsSecret is a reference to a secret containing authentication details for the IBM Security Verify server
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Secret Containing the Credentials",xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"}
// +kubebuilder:validation:Required
CredentialsSecret *ObjectRef `json:"credentialsSecret"`
// Groups is the list of ISV groups to synchronize
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Groups to Synchronize",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
// +kubebuilder:validation:Required
Groups []IsvGroupSpec `json:"groups,omitempty"`
// TenantURL is the location of the IBM Security Verify tenant
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tenant URL",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
// +kubebuilder:validation:Required
TenantURL string `json:"tenantUrl"`
}

// +k8s:openapi-gen=true
type IsvGroupSpec struct {
// The display name of the group as defined in IBM Security Verify
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
// +kubebuilder:validation:Required
Name string `json:"name,omitempty"`
// The ID of the group as defined in IBM Security Verify. This value can be found by using the API.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Id",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
// +kubebuilder:validation:Required
Id string `json:"id,omitempty"`
}

// ObjectRef represents a reference to an item within a Secret
// +k8s:openapi-gen=true
type ObjectRef struct {
Expand Down
48 changes: 48 additions & 0 deletions config/crd/bases/redhatcop.redhat.io_groupsyncs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,54 @@ spec:
- realm
- url
type: object
ibmsecurityverify:
description: The IBM Security Verify (ISV) provider
properties:
credentialsSecret:
description: CredentialsSecret is a reference to a secret containing authentication details for the ISV server
properties:
key:
description: Key represents the specific key to reference from the resource
type: string
kind:
default: Secret
description: Kind is a string value representing the resource type
enum:
- ConfigMap
- Secret
type: string
name:
description: Name represents the name of the resource
type: string
namespace:
description: Namespace represents the namespace containing the resource
type: string
required:
- name
- namespace
type: object
groups:
description: The ISV groups to synchronize
type: array
items:
type: object
properties:
name:
description: Name of the ISV group
type: string
id:
description: ID of the ISV group
type: string
required:
- id
tenantUrl:
description: URL for the ISV server of the tenant
type: string
required:
- credentialsSecret
- tenantUrl
- groups
type: object
ldap:
description: Ldap represents the LDAP provider
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ spec:
* [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
* [Keycloak](https://www.keycloak.org/)/[Red Hat Single Sign On](https://access.redhat.com/products/red-hat-single-sign-on)
* [Okta](https://www.okta.com/)
* [IBM Security Verify](https://docs.verify.ibm.com/verify)
The following sections describe the configuration options available for each provider
Expand Down Expand Up @@ -1162,6 +1163,54 @@ spec:
```shell
oc create secret generic okta-api-token --from-literal=okta-api-token=<OKTA_API_TOKEN> -n group-sync-operator
```
### IBM Security Verify
Groups defined in [IBM Security Verify](https://help.okta.com/en/prod/Content/Topics/users-groups-profiles/usgp-main.htm) (ISV) can be synchronized into OpenShift. Currently only the `userName` field from ISV will be synchronized. The developer docs for the ISV API can be found [here](https://docs.verify.ibm.com/verify/page/api-documentation).
The following table describes the set of configuration options for the provider:
| Name | Description | Defaults | Required |
| ----- | ---------- | -------- | ----- |
| `credentialsSecret` | Reference to a secret containing authentication details (see below) | `''` | Yes |
| `groups` | List of groups to synchronize (see below) | `nil` | Yes |
| `tenantUrl` | The ISV tenant URL, for example `https://my-isv.verify.ibm.com`) | `''` | Yes |
The following is an example of a minimal configuration that can be applied to integrate with an Okta provider:
```yaml
apiVersion: redhatcop.redhat.io/v1alpha1
kind: GroupSync
metadata:
name: ibmsecurityverify-sync
spec:
providers:
- name: ibmsecurityverify
ibmsecurityverify:
credentialsSecret:
name: isv-group-sync
namespace: group-sync-operator
tenantUrl: https://my-isv.verify.ibm.com
groups:
- name: 'application owners'
id: 645001V3V9
- name: developer
id: 645001V3VA
```
#### Group Objects
Each group object in the `groups` array must contain an `id` field. The group ID can be retrieved by pulling the group information from the ISV API. Optionally, the object may also contain a `name` which corresponds to the group's display name. When defined, the operator will confirm that the name defined in the YAML matches that received from the API when synchronization occurs; as the group IDs are not human-friendly, using the name can confirm the correct groups are configured. If the names do not match an error will be logged.
#### Group Names
The name of each groups created in OpenShift will match the group name in ISV. Any whitespace in the ISV group name will be replaced with a hyphen.
#### Authenticating to IBM Security Verify
A secret must be created in the same namespace as the group-sync-operator pod. It must contain the following keys:
* `clientId` - The API client ID.
* `clientSecret`- The API client secret.
See the IBM Security Verify [API documentation](https://docs.verify.ibm.com/verify/docs/api-access) for setting up authentication.
### Support for Additional Metadata (Beta)
Expand Down
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/redhat-cop/group-sync-operator

go 1.21.10
go 1.21.13

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0
Expand Down Expand Up @@ -33,6 +33,8 @@ require (
sigs.k8s.io/controller-runtime v0.13.1
)

require github.com/stretchr/objx v0.5.2 // indirect

require (
cloud.google.com/go v0.97.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect
Expand Down Expand Up @@ -70,7 +72,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.12 // indirect
Expand All @@ -80,7 +82,7 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/microsoft/kiota-abstractions-go v0.19.0 // indirect
github.com/microsoft/kiota-serialization-form-go v0.9.1 // indirect
Expand All @@ -107,7 +109,7 @@ require (
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
Expand All @@ -117,7 +119,7 @@ require (
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,14 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
Expand Down Expand Up @@ -509,6 +512,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
Expand Down Expand Up @@ -705,6 +710,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand All @@ -716,6 +723,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
Expand Down Expand Up @@ -995,8 +1004,11 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
Expand Down
Loading

0 comments on commit 488828b

Please sign in to comment.