Skip to content

Commit

Permalink
operator: Adds CCO support to openshift AWS STS use-case
Browse files Browse the repository at this point in the history
  • Loading branch information
JoaoBraveCoding committed Jan 5, 2024
1 parent 82099eb commit 62fec93
Show file tree
Hide file tree
Showing 22 changed files with 313 additions and 45 deletions.
3 changes: 3 additions & 0 deletions operator/apis/loki/v1/lokistack_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,9 @@ const (
ReasonMissingObjectStorageSecret LokiStackConditionReason = "MissingObjectStorageSecret"
// ReasonInvalidObjectStorageSecret when the format of the secret is invalid.
ReasonInvalidObjectStorageSecret LokiStackConditionReason = "InvalidObjectStorageSecret"
// ReasonMissingManagedAuthSecret when the required secret for managed auth credentials to object
// storage is missing.
ReasonMissingManagedAuthSecret LokiStackConditionReason = "MissingManagedAuthenticationSecret"
// ReasonInvalidObjectStorageSchema when the spec contains an invalid schema(s).
ReasonInvalidObjectStorageSchema LokiStackConditionReason = "InvalidObjectStorageSchema"
// ReasonMissingObjectStorageCAConfigMap when the required configmap to verify object storage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: docker.io/grafana/loki-operator:0.5.0
createdAt: "2023-12-12T09:22:19Z"
createdAt: "2024-01-04T16:42:25Z"
description: The Community Loki Operator provides Kubernetes native deployment
and management of Loki and related logging components.
features.operators.openshift.io/disconnected: "true"
features.operators.openshift.io/fips-compliant: "false"
features.operators.openshift.io/proxy-aware: "true"
features.operators.openshift.io/tls-profiles: "true"
features.operators.openshift.io/token-auth-aws: "false"
features.operators.openshift.io/token-auth-aws: "true"
features.operators.openshift.io/token-auth-azure: "false"
features.operators.openshift.io/token-auth-gcp: "false"
operators.operatorframework.io/builder: operator-sdk-unknown
Expand Down Expand Up @@ -1463,6 +1463,18 @@ spec:
- patch
- update
- watch
- apiGroups:
- cloudcredential.openshift.io
resources:
- credentialsrequests
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- config.openshift.io
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: docker.io/grafana/loki-operator:0.5.0
createdAt: "2023-12-12T09:22:17Z"
createdAt: "2024-01-04T16:42:23Z"
description: The Community Loki Operator provides Kubernetes native deployment
and management of Loki and related logging components.
operators.operatorframework.io/builder: operator-sdk-unknown
Expand Down Expand Up @@ -1443,6 +1443,18 @@ spec:
- patch
- update
- watch
- apiGroups:
- cloudcredential.openshift.io
resources:
- credentialsrequests
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- config.openshift.io
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: quay.io/openshift-logging/loki-operator:0.1.0
createdAt: "2023-12-12T09:22:21Z"
createdAt: "2024-01-04T16:42:26Z"
description: |
The Loki Operator for OCP provides a means for configuring and managing a Loki stack for cluster logging.
## Prerequisites and Requirements
Expand All @@ -164,7 +164,7 @@ metadata:
features.operators.openshift.io/fips-compliant: "false"
features.operators.openshift.io/proxy-aware: "true"
features.operators.openshift.io/tls-profiles: "true"
features.operators.openshift.io/token-auth-aws: "false"
features.operators.openshift.io/token-auth-aws: "true"
features.operators.openshift.io/token-auth-azure: "false"
features.operators.openshift.io/token-auth-gcp: "false"
olm.skipRange: '>=5.7.0-0 <5.9.0'
Expand Down Expand Up @@ -1448,6 +1448,18 @@ spec:
- patch
- update
- watch
- apiGroups:
- cloudcredential.openshift.io
resources:
- credentialsrequests
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- config.openshift.io
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ metadata:
features.operators.openshift.io/fips-compliant: "false"
features.operators.openshift.io/proxy-aware: "true"
features.operators.openshift.io/tls-profiles: "true"
features.operators.openshift.io/token-auth-aws: "false"
features.operators.openshift.io/token-auth-aws: "true"
features.operators.openshift.io/token-auth-azure: "false"
features.operators.openshift.io/token-auth-gcp: "false"
repository: https://github.com/grafana/loki/tree/main/operator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ metadata:
features.operators.openshift.io/fips-compliant: "false"
features.operators.openshift.io/proxy-aware: "true"
features.operators.openshift.io/tls-profiles: "true"
features.operators.openshift.io/token-auth-aws: "false"
features.operators.openshift.io/token-auth-aws: "true"
features.operators.openshift.io/token-auth-azure: "false"
features.operators.openshift.io/token-auth-gcp: "false"
olm.skipRange: '>=5.7.0-0 <5.9.0'
Expand Down
12 changes: 12 additions & 0 deletions operator/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ rules:
- patch
- update
- watch
- apiGroups:
- cloudcredential.openshift.io
resources:
- credentialsrequests
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- config.openshift.io
resources:
Expand Down
5 changes: 4 additions & 1 deletion operator/controllers/loki/lokistack_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/google/go-cmp/cmp"
openshiftconfigv1 "github.com/openshift/api/config/v1"
routev1 "github.com/openshift/api/route/v1"
cloudcredentialv1 "github.com/openshift/cloud-credential-operator/pkg/apis/cloudcredential/v1"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -129,6 +130,7 @@ type LokiStackReconciler struct {
// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;create;update
// +kubebuilder:rbac:groups=config.openshift.io,resources=dnses;apiservers;proxies,verbs=get;list;watch
// +kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update;delete
// +kubebuilder:rbac:groups=cloudcredential.openshift.io,resources=credentialsrequests,verbs=get;list;watch;create;update;patch;delete

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down Expand Up @@ -213,7 +215,8 @@ func (r *LokiStackReconciler) buildController(bld k8s.Builder) error {
}

if r.FeatureGates.OpenShift.Enabled {
bld = bld.Owns(&routev1.Route{}, updateOrDeleteOnlyPred)
bld = bld.Owns(&routev1.Route{}, updateOrDeleteOnlyPred).
Owns(&cloudcredentialv1.CredentialsRequest{}, updateOrDeleteOnlyPred)
} else {
bld = bld.Owns(&networkingv1.Ingress{}, updateOrDeleteOnlyPred)
}
Expand Down
2 changes: 1 addition & 1 deletion operator/controllers/loki/lokistack_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func TestLokiStackController_RegisterOwnedResourcesForUpdateOrDeleteOnly(t *test
{
obj: &routev1.Route{},
index: 10,
ownCallsCount: 11,
ownCallsCount: 12,
featureGates: configv1.FeatureGates{
OpenShift: configv1.OpenShiftFeatureGates{
Enabled: true,
Expand Down
4 changes: 4 additions & 0 deletions operator/docs/operator/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,10 @@ for authentication is missing.</p>
<td><p>ReasonMissingGatewayTenantSecret when the required tenant secret
for authentication is missing.</p>
</td>
</tr><tr><td><p>&#34;MissingManagedAuthenticationSecret&#34;</p></td>
<td><p>ReasonMissingManagedAuthSecret when the required secret for managed auth credentials to object
storage is missing.</p>
</td>
</tr><tr><td><p>&#34;MissingObjectStorageCAConfigMap&#34;</p></td>
<td><p>ReasonMissingObjectStorageCAConfigMap when the required configmap to verify object storage
certificates is missing.</p>
Expand Down
9 changes: 7 additions & 2 deletions operator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ require (
sigs.k8s.io/yaml v1.3.0
)

require (
github.com/openshift/cloud-credential-operator v0.0.0-20231220062235-fba5608095b6
gopkg.in/ini.v1 v1.67.0
)

require (
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
Expand Down Expand Up @@ -124,8 +129,8 @@ require (
go.etcd.io/etcd/api/v3 v3.5.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect
go.etcd.io/etcd/client/v3 v3.5.7 // indirect
go.opentelemetry.io/otel v1.11.2 // indirect
go.opentelemetry.io/otel/trace v1.11.2 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/goleak v1.2.1 // indirect
go.uber.org/multierr v1.8.0 // indirect
Expand Down
15 changes: 9 additions & 6 deletions operator/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRsugc=
github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg=
github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down Expand Up @@ -498,6 +498,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/openshift/api v0.0.0-20231031181504-3be12e93388f h1:j7QYl057TBD/lxWAGCr4IrbdG7IMg2U60DFK+BKt3VI=
github.com/openshift/api v0.0.0-20231031181504-3be12e93388f/go.mod h1:yimSGmjsI+XF1mr+AKBs2//fSXIOhhetHGbMlBEfXbs=
github.com/openshift/cloud-credential-operator v0.0.0-20231220062235-fba5608095b6 h1:AYQu3PutGYqo1GHRhSp2p3sZ0r+Rof3v4JOjpLPlhmI=
github.com/openshift/cloud-credential-operator v0.0.0-20231220062235-fba5608095b6/go.mod h1:lJrOiZCRs1ydNqBjsdZ+LHgLmF4P6RNMfFtAcGkzbY0=
github.com/openshift/library-go v0.0.0-20231103161458-0ec67489d123 h1:JfXG50f8yVud5xakwTHoqD00+3HYdLmZuEqn5Sq8ZRQ=
github.com/openshift/library-go v0.0.0-20231103161458-0ec67489d123/go.mod h1:ZFwNwC3opc/7aOvzUbU95zp33Lbxet48h80ryH3p6DY=
github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc=
Expand Down Expand Up @@ -634,10 +636,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0=
go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0=
go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
Expand Down Expand Up @@ -1182,7 +1184,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
57 changes: 54 additions & 3 deletions operator/internal/handlers/internal/storage/secrets.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package storage

import (
"bytes"
"crypto/sha1"
"errors"
"fmt"
"sort"

"github.com/ViaQ/logerr/v2/kverrors"
"gopkg.in/ini.v1"
corev1 "k8s.io/api/core/v1"

lokiv1 "github.com/grafana/loki/operator/apis/loki/v1"
Expand All @@ -15,7 +18,7 @@ import (
var hashSeparator = []byte(",")

// ExtractSecret reads a k8s secret into a manifest object storage struct if valid.
func ExtractSecret(s *corev1.Secret, secretType lokiv1.ObjectStorageSecretType) (*storage.Options, error) {
func ExtractSecret(s *corev1.Secret, secretType lokiv1.ObjectStorageSecretType, managedAuthSecret *corev1.Secret) (*storage.Options, error) {
hash, err := hashSecretData(s)
if err != nil {
return nil, kverrors.Wrap(err, "error calculating hash for secret", "type", secretType)
Expand All @@ -33,7 +36,7 @@ func ExtractSecret(s *corev1.Secret, secretType lokiv1.ObjectStorageSecretType)
case lokiv1.ObjectStorageSecretGCS:
storageOpts.GCS, err = extractGCSConfigSecret(s)
case lokiv1.ObjectStorageSecretS3:
storageOpts.S3, err = extractS3ConfigSecret(s)
storageOpts.S3, err = extractS3ConfigSecret(s, managedAuthSecret)
case lokiv1.ObjectStorageSecretSwift:
storageOpts.Swift, err = extractSwiftConfigSecret(s)
case lokiv1.ObjectStorageSecretAlibabaCloud:
Expand Down Expand Up @@ -124,7 +127,7 @@ func extractGCSConfigSecret(s *corev1.Secret) (*storage.GCSStorageConfig, error)
}, nil
}

func extractS3ConfigSecret(s *corev1.Secret) (*storage.S3StorageConfig, error) {
func extractS3ConfigSecret(s *corev1.Secret, managedAuthSecret *corev1.Secret) (*storage.S3StorageConfig, error) {
// Extract and validate mandatory fields
buckets := s.Data[storage.KeyAWSBucketNames]
if len(buckets) == 0 {
Expand Down Expand Up @@ -155,6 +158,22 @@ func extractS3ConfigSecret(s *corev1.Secret) (*storage.S3StorageConfig, error) {
}

switch {
case managedAuthSecret != nil:
cfg.STS = true
cfg.Audience = "openshift"
cfg.RoleARN, err = extractSTSSecret(managedAuthSecret)
if err != nil {
return nil, err
}
if len(roleArn) != 0 {
return nil, kverrors.New("extra secret field set", "field", storage.KeyAWSRoleArn)
}
// In the STS case region is not an optional field
if len(region) == 0 {
return nil, kverrors.New("missing secret field", "field", storage.KeyAWSRegion)
}

return cfg, nil
case len(roleArn) == 0:
cfg.Endpoint = string(endpoint)

Expand Down Expand Up @@ -299,3 +318,35 @@ func extractAlibabaCloudConfigSecret(s *corev1.Secret) (*storage.AlibabaCloudSto
Bucket: string(bucket),
}, nil
}

var (
errMissingAWSCredentials = errors.New("missing CCO secret for AWS STS authentication")
errInvalidAWSCredentials = errors.New("invalid credentials file")
)

func extractSTSSecret(s *corev1.Secret) (string, error) {
var data []byte
switch {
case len(s.Data["credentials"]) > 0:
data = s.Data["credentials"]
default:
return "", errMissingAWSCredentials
}

cfg, err := ini.Load(bytes.NewReader(data))
if err != nil {
return "", errInvalidAWSCredentials
}

section, err := cfg.GetSection("default")
if err != nil {
return "", err
}

roleARN, err := section.GetKey("role_arn")
if err != nil {
return "", err
}

return roleARN.String(), nil
}
Loading

0 comments on commit 62fec93

Please sign in to comment.