Skip to content

Commit 488828b

Browse files
authored
feat: IBM Security Verify provider (#328)
* 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
1 parent 35ee051 commit 488828b

13 files changed

+578
-14
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ bin
3535
*.swo
3636
*~
3737
buildtools/yq
38+
39+
# binaries
40+
manager
41+
group-sync-operator
42+
43+
# temporary files
44+
tmp/

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build the manager binary
2-
FROM golang:1.18 as builder
2+
FROM golang:1.21 as builder
33

44
WORKDIR /workspace
55
# Copy the Go Modules manifests

README.md

+49
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Integration with external systems is made possible through a set of pluggable ex
6363
* [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
6464
* [Keycloak](https://www.keycloak.org/)/[Red Hat Single Sign On](https://access.redhat.com/products/red-hat-single-sign-on)
6565
* [Okta](https://www.okta.com/)
66+
* [IBM Security Verify](https://docs.verify.ibm.com/verify)
6667
6768
The following sections describe the configuration options available for each provider
6869
@@ -477,6 +478,54 @@ The secret can be created by executing the following command:
477478
oc create secret generic okta-api-token --from-literal=okta-api-token=<OKTA_API_TOKEN> -n group-sync-operator
478479
```
479480

481+
### IBM Security Verify
482+
483+
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).
484+
The following table describes the set of configuration options for the provider:
485+
486+
| Name | Description | Defaults | Required |
487+
| ----- | ---------- | -------- | ----- |
488+
| `credentialsSecret` | Reference to a secret containing authentication details (see below) | `''` | Yes |
489+
| `groups` | List of groups to synchronize (see below) | `nil` | Yes |
490+
| `tenantUrl` | The ISV tenant URL, for example `https://my-isv.verify.ibm.com`) | `''` | Yes |
491+
492+
The following is an example of a minimal configuration that can be applied to integrate with an Okta provider:
493+
494+
```yaml
495+
apiVersion: redhatcop.redhat.io/v1alpha1
496+
kind: GroupSync
497+
metadata:
498+
name: ibmsecurityverify-sync
499+
spec:
500+
providers:
501+
- name: ibmsecurityverify
502+
ibmsecurityverify:
503+
credentialsSecret:
504+
name: isv-group-sync
505+
namespace: group-sync-operator
506+
tenantUrl: https://my-isv.verify.ibm.com
507+
groups:
508+
- name: 'application owners'
509+
id: 645001V3V9
510+
- name: developer
511+
id: 645001V3VA
512+
```
513+
514+
#### Group Objects
515+
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.
516+
517+
#### Group Names
518+
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.
519+
520+
#### Authenticating to IBM Security Verify
521+
522+
A secret must be created in the same namespace as the group-sync-operator pod. It must contain the following keys:
523+
524+
* `clientId` - The API client ID.
525+
* `clientSecret`- The API client secret.
526+
527+
See the IBM Security Verify [API documentation](https://docs.verify.ibm.com/verify/docs/api-access) for setting up authentication.
528+
480529
### Support for Additional Metadata (Beta)
481530

482531
Additional metadata based on Keycloak group are also added to the OpenShift groups as Annotations including:

api/v1alpha1/groupsync_types.go

+34
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ type ProviderType struct {
138138
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Okta Provider"
139139
// +kubebuilder:validation:Optional
140140
Okta *OktaProvider `json:"okta,omitempty"`
141+
142+
// IbmSecurityVerify represents the IBM Security Verify provider
143+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="IBM Security Verify"
144+
// +kubebuilder:validation:Optional
145+
IbmSecurityVerify *IbmSecurityVerifyProvider `json:"ibmsecurityverify,omitempty"`
141146
}
142147

143148
// KeycloakProvider represents integration with Keycloak
@@ -462,6 +467,35 @@ type OktaProvider struct {
462467
Prune bool `json:"prune"`
463468
}
464469

470+
// IbmSecurityVerifyProvider represents integration with IBM Security Verify
471+
// +k8s:openapi-gen=true
472+
type IbmSecurityVerifyProvider struct {
473+
// CredentialsSecret is a reference to a secret containing authentication details for the IBM Security Verify server
474+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Secret Containing the Credentials",xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"}
475+
// +kubebuilder:validation:Required
476+
CredentialsSecret *ObjectRef `json:"credentialsSecret"`
477+
// Groups is the list of ISV groups to synchronize
478+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Groups to Synchronize",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
479+
// +kubebuilder:validation:Required
480+
Groups []IsvGroupSpec `json:"groups,omitempty"`
481+
// TenantURL is the location of the IBM Security Verify tenant
482+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tenant URL",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
483+
// +kubebuilder:validation:Required
484+
TenantURL string `json:"tenantUrl"`
485+
}
486+
487+
// +k8s:openapi-gen=true
488+
type IsvGroupSpec struct {
489+
// The display name of the group as defined in IBM Security Verify
490+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
491+
// +kubebuilder:validation:Required
492+
Name string `json:"name,omitempty"`
493+
// The ID of the group as defined in IBM Security Verify. This value can be found by using the API.
494+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Id",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"}
495+
// +kubebuilder:validation:Required
496+
Id string `json:"id,omitempty"`
497+
}
498+
465499
// ObjectRef represents a reference to an item within a Secret
466500
// +k8s:openapi-gen=true
467501
type ObjectRef struct {

config/crd/bases/redhatcop.redhat.io_groupsyncs.yaml

+48
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,54 @@ spec:
440440
- realm
441441
- url
442442
type: object
443+
ibmsecurityverify:
444+
description: The IBM Security Verify (ISV) provider
445+
properties:
446+
credentialsSecret:
447+
description: CredentialsSecret is a reference to a secret containing authentication details for the ISV server
448+
properties:
449+
key:
450+
description: Key represents the specific key to reference from the resource
451+
type: string
452+
kind:
453+
default: Secret
454+
description: Kind is a string value representing the resource type
455+
enum:
456+
- ConfigMap
457+
- Secret
458+
type: string
459+
name:
460+
description: Name represents the name of the resource
461+
type: string
462+
namespace:
463+
description: Namespace represents the namespace containing the resource
464+
type: string
465+
required:
466+
- name
467+
- namespace
468+
type: object
469+
groups:
470+
description: The ISV groups to synchronize
471+
type: array
472+
items:
473+
type: object
474+
properties:
475+
name:
476+
description: Name of the ISV group
477+
type: string
478+
id:
479+
description: ID of the ISV group
480+
type: string
481+
required:
482+
- id
483+
tenantUrl:
484+
description: URL for the ISV server of the tenant
485+
type: string
486+
required:
487+
- credentialsSecret
488+
- tenantUrl
489+
- groups
490+
type: object
443491
ldap:
444492
description: Ldap represents the LDAP provider
445493
properties:

config/manifests/bases/group-sync-operator.clusterserviceversion.yaml

+49
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ spec:
766766
* [LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
767767
* [Keycloak](https://www.keycloak.org/)/[Red Hat Single Sign On](https://access.redhat.com/products/red-hat-single-sign-on)
768768
* [Okta](https://www.okta.com/)
769+
* [IBM Security Verify](https://docs.verify.ibm.com/verify)
769770
770771
The following sections describe the configuration options available for each provider
771772
@@ -1162,6 +1163,54 @@ spec:
11621163
```shell
11631164
oc create secret generic okta-api-token --from-literal=okta-api-token=<OKTA_API_TOKEN> -n group-sync-operator
11641165
```
1166+
1167+
### IBM Security Verify
1168+
1169+
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).
1170+
The following table describes the set of configuration options for the provider:
1171+
1172+
| Name | Description | Defaults | Required |
1173+
| ----- | ---------- | -------- | ----- |
1174+
| `credentialsSecret` | Reference to a secret containing authentication details (see below) | `''` | Yes |
1175+
| `groups` | List of groups to synchronize (see below) | `nil` | Yes |
1176+
| `tenantUrl` | The ISV tenant URL, for example `https://my-isv.verify.ibm.com`) | `''` | Yes |
1177+
1178+
The following is an example of a minimal configuration that can be applied to integrate with an Okta provider:
1179+
1180+
```yaml
1181+
apiVersion: redhatcop.redhat.io/v1alpha1
1182+
kind: GroupSync
1183+
metadata:
1184+
name: ibmsecurityverify-sync
1185+
spec:
1186+
providers:
1187+
- name: ibmsecurityverify
1188+
ibmsecurityverify:
1189+
credentialsSecret:
1190+
name: isv-group-sync
1191+
namespace: group-sync-operator
1192+
tenantUrl: https://my-isv.verify.ibm.com
1193+
groups:
1194+
- name: 'application owners'
1195+
id: 645001V3V9
1196+
- name: developer
1197+
id: 645001V3VA
1198+
```
1199+
1200+
#### Group Objects
1201+
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.
1202+
1203+
#### Group Names
1204+
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.
1205+
1206+
#### Authenticating to IBM Security Verify
1207+
1208+
A secret must be created in the same namespace as the group-sync-operator pod. It must contain the following keys:
1209+
1210+
* `clientId` - The API client ID.
1211+
* `clientSecret`- The API client secret.
1212+
1213+
See the IBM Security Verify [API documentation](https://docs.verify.ibm.com/verify/docs/api-access) for setting up authentication.
11651214
11661215
### Support for Additional Metadata (Beta)
11671216

go.mod

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/redhat-cop/group-sync-operator
22

3-
go 1.21.10
3+
go 1.21.13
44

55
require (
66
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0
@@ -33,6 +33,8 @@ require (
3333
sigs.k8s.io/controller-runtime v0.13.1
3434
)
3535

36+
require github.com/stretchr/objx v0.5.2 // indirect
37+
3638
require (
3739
cloud.google.com/go v0.97.0 // indirect
3840
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect
@@ -70,7 +72,7 @@ require (
7072
github.com/google/go-querystring v1.1.0 // indirect
7173
github.com/google/gofuzz v1.1.0 // indirect
7274
github.com/google/uuid v1.3.0 // indirect
73-
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
75+
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
7476
github.com/hashicorp/golang-lru v0.5.4 // indirect
7577
github.com/huandu/xstrings v1.3.3 // indirect
7678
github.com/imdario/mergo v0.3.12 // indirect
@@ -80,7 +82,7 @@ require (
8082
github.com/kylelemons/godebug v1.1.0 // indirect
8183
github.com/mailru/easyjson v0.7.6 // indirect
8284
github.com/mattn/go-colorable v0.1.13 // indirect
83-
github.com/mattn/go-isatty v0.0.16 // indirect
85+
github.com/mattn/go-isatty v0.0.20 // indirect
8486
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
8587
github.com/microsoft/kiota-abstractions-go v0.19.0 // indirect
8688
github.com/microsoft/kiota-serialization-form-go v0.9.1 // indirect
@@ -107,7 +109,7 @@ require (
107109
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f // indirect
108110
github.com/spf13/cast v1.3.1 // indirect
109111
github.com/spf13/pflag v1.0.5 // indirect
110-
github.com/stretchr/testify v1.8.2 // indirect
112+
github.com/stretchr/testify v1.9.0 // indirect
111113
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
112114
go.opentelemetry.io/otel v1.14.0 // indirect
113115
go.opentelemetry.io/otel/trace v1.14.0 // indirect
@@ -117,7 +119,7 @@ require (
117119
golang.org/x/crypto v0.17.0 // indirect
118120
golang.org/x/net v0.17.0 // indirect
119121
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
120-
golang.org/x/sys v0.15.0 // indirect
122+
golang.org/x/sys v0.20.0 // indirect
121123
golang.org/x/term v0.15.0 // indirect
122124
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
123125
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect

go.sum

+12
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,14 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
419419
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
420420
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
421421
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
422+
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
422423
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
423424
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
424425
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
425426
github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
426427
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
428+
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
429+
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
427430
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
428431
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
429432
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
@@ -509,6 +512,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
509512
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
510513
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
511514
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
515+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
516+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
512517
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
513518
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
514519
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
@@ -705,6 +710,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
705710
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
706711
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
707712
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
713+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
714+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
708715
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
709716
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
710717
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -716,6 +723,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
716723
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
717724
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
718725
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
726+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
727+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
719728
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
720729
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
721730
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -995,8 +1004,11 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
9951004
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9961005
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9971006
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1007+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9981008
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
9991009
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1010+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
1011+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
10001012
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
10011013
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
10021014
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=

0 commit comments

Comments
 (0)