feat(operator): Change attribute value used for CCO-based credential mode (#12165)

pull/12182/head
Joao Marcal 1 year ago committed by GitHub
parent a0fce39169
commit 3eee541b1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      operator/CHANGELOG.md
  2. 4
      operator/apis/config/v1/projectconfig_types.go
  3. 22
      operator/apis/loki/v1/lokistack_types.go
  4. 2
      operator/bundle/community-openshift/manifests/loki-operator.clusterserviceversion.yaml
  5. 4
      operator/bundle/community-openshift/manifests/loki.grafana.com_lokistacks.yaml
  6. 2
      operator/bundle/community/manifests/loki-operator.clusterserviceversion.yaml
  7. 4
      operator/bundle/community/manifests/loki.grafana.com_lokistacks.yaml
  8. 2
      operator/bundle/openshift/manifests/loki-operator.clusterserviceversion.yaml
  9. 4
      operator/bundle/openshift/manifests/loki.grafana.com_lokistacks.yaml
  10. 4
      operator/config/crd/bases/loki.grafana.com_lokistacks.yaml
  11. 4
      operator/controllers/loki/lokistack_controller.go
  12. 27
      operator/docs/operator/api.md
  13. 4
      operator/docs/operator/feature-gates.md
  14. 2
      operator/hack/deploy-aws-storage-secret.sh
  15. 8
      operator/internal/config/managed_auth.go
  16. 10
      operator/internal/config/options.go
  17. 6
      operator/internal/handlers/credentialsrequest.go
  18. 20
      operator/internal/handlers/credentialsrequest_test.go
  19. 40
      operator/internal/handlers/internal/storage/secrets.go
  20. 52
      operator/internal/handlers/internal/storage/secrets_test.go
  21. 12
      operator/internal/handlers/internal/storage/storage.go
  22. 12
      operator/internal/handlers/internal/storage/storage_test.go
  23. 4
      operator/internal/manifests/openshift/credentialsrequest.go
  24. 8
      operator/internal/manifests/openshift/credentialsrequest_test.go
  25. 2
      operator/internal/manifests/openshift/options.go
  26. 32
      operator/internal/manifests/storage/configure.go
  27. 22
      operator/internal/manifests/storage/configure_test.go
  28. 2
      operator/internal/manifests/storage/options.go
  29. 4
      operator/internal/manifests/storage/var.go
  30. 6
      operator/internal/manifests/var.go
  31. 8
      operator/main.go

@ -1,5 +1,6 @@
## Main
- [12165](https://github.com/grafana/loki/pull/12165) **JoaoBraveCoding**: Change attribute value used for CCO-based credential mode
- [12157](https://github.com/grafana/loki/pull/12157) **periklis**: Fix managed auth features annotation for community-openshift bundle
- [12104](https://github.com/grafana/loki/pull/12104) **periklis**: Upgrade build and runtime dependencies
- [11928](https://github.com/grafana/loki/pull/11928) **periklis**: Fix remote write client timeout config rename

@ -52,9 +52,9 @@ type OpenShiftFeatureGates struct {
// Dashboards enables the loki-mixin dashboards into the OpenShift Console
Dashboards bool `json:"dashboards,omitempty"`
// ManagedAuthEnv is true when OpenShift-functions are enabled and the operator has detected
// TokenCCOAuthEnv is true when OpenShift-functions are enabled and the operator has detected
// that it is running with some kind of "workload identity" (AWS STS, Azure WIF) enabled.
ManagedAuthEnv bool
TokenCCOAuthEnv bool
}
// FeatureGates is the supported set of all operator feature gates.

@ -1070,12 +1070,10 @@ const (
ReasonMissingObjectStorageSecret LokiStackConditionReason = "MissingObjectStorageSecret"
// ReasonInvalidObjectStorageSecret when the format of the secret is invalid.
ReasonInvalidObjectStorageSecret LokiStackConditionReason = "InvalidObjectStorageSecret"
// ReasonMissingCredentialsRequest when the required request for managed auth credentials to object
// storage is missing.
ReasonMissingCredentialsRequest LokiStackConditionReason = "MissingCredentialsRequest"
// ReasonMissingManagedAuthSecret when the required secret for managed auth credentials to object
// storage is missing.
ReasonMissingManagedAuthSecret LokiStackConditionReason = "MissingManagedAuthenticationSecret"
// ReasonMissingTokenCCOAuthSecret when the secret generated by CCO for token authentication is missing.
// This is usually a transient error because the secret is not immediately available after creating the
// CredentialsRequest, but it can persist if the CCO or its configuration are incorrect.
ReasonMissingTokenCCOAuthSecret LokiStackConditionReason = "MissingTokenCCOAuthenticationSecret"
// ReasonInvalidObjectStorageSchema when the spec contains an invalid schema(s).
ReasonInvalidObjectStorageSchema LokiStackConditionReason = "InvalidObjectStorageSchema"
// ReasonMissingObjectStorageCAConfigMap when the required configmap to verify object storage
@ -1204,7 +1202,7 @@ type LokiStackComponentStatus struct {
// CredentialMode represents the type of authentication used for accessing the object storage.
//
// +kubebuilder:validation:Enum=static;token;managed
// +kubebuilder:validation:Enum=static;token;token-cco
type CredentialMode string
const (
@ -1216,11 +1214,11 @@ const (
// Instead, they are generated during runtime using a service, which allows for shorter-lived credentials and
// much more granular control. This authentication mode is not supported for all object storage types.
CredentialModeToken CredentialMode = "token"
// CredentialModeManaged represents the usage of short-lived tokens retrieved from a credential source.
// This mode is similar to CredentialModeToken,but instead of having a user-configured credential source,
// it is configured by the environment, for example the Cloud Credential Operator in OpenShift.
// This mode is only supported for certain object storage types in certain runtime environments.
CredentialModeManaged CredentialMode = "managed"
// CredentialModeTokenCCO represents the usage of short-lived tokens retrieved from a credential source.
// This mode is similar to CredentialModeToken, but instead of having a user-configured credential source,
// it is configured by the environment and the operator relies on the Cloud Credential Operator to provide
// a secret. This mode is only supported for certain object storage types in certain runtime environments.
CredentialModeTokenCCO CredentialMode = "token-cco"
)
// LokiStackStorageStatus defines the observed state of

@ -150,7 +150,7 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: docker.io/grafana/loki-operator:0.5.0
createdAt: "2024-03-11T16:01:17Z"
createdAt: "2024-03-12T09:52:37Z"
description: The Community Loki Operator provides Kubernetes native deployment
and management of Loki and related logging components.
features.operators.openshift.io/disconnected: "true"

@ -635,7 +635,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
name:
description: Name of a secret in the namespace configured
@ -3819,7 +3819,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
schemas:
description: |-

@ -150,7 +150,7 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: docker.io/grafana/loki-operator:0.5.0
createdAt: "2024-03-11T16:01:16Z"
createdAt: "2024-03-12T09:52:36Z"
description: The Community Loki Operator provides Kubernetes native deployment
and management of Loki and related logging components.
operators.operatorframework.io/builder: operator-sdk-unknown

@ -635,7 +635,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
name:
description: Name of a secret in the namespace configured
@ -3819,7 +3819,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
schemas:
description: |-

@ -150,7 +150,7 @@ metadata:
categories: OpenShift Optional, Logging & Tracing
certified: "false"
containerImage: quay.io/openshift-logging/loki-operator:0.1.0
createdAt: "2024-03-11T16:01:19Z"
createdAt: "2024-03-12T09:52:39Z"
description: |
The Loki Operator for OCP provides a means for configuring and managing a Loki stack for cluster logging.
## Prerequisites and Requirements

@ -635,7 +635,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
name:
description: Name of a secret in the namespace configured
@ -3819,7 +3819,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
schemas:
description: |-

@ -617,7 +617,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
name:
description: Name of a secret in the namespace configured
@ -3801,7 +3801,7 @@ spec:
enum:
- static
- token
- managed
- token-cco
type: string
schemas:
description: |-

@ -110,7 +110,7 @@ type LokiStackReconciler struct {
Log logr.Logger
Scheme *runtime.Scheme
FeatureGates configv1.FeatureGates
AuthConfig *config.ManagedAuthConfig
AuthConfig *config.TokenCCOAuthConfig
}
// +kubebuilder:rbac:groups=loki.grafana.com,resources=lokistacks,verbs=get;list;watch;create;update;patch;delete
@ -179,7 +179,7 @@ func (r *LokiStackReconciler) updateResources(ctx context.Context, req ctrl.Requ
}
}
if r.FeatureGates.OpenShift.ManagedAuthEnv {
if r.FeatureGates.OpenShift.TokenCCOAuthEnv {
if err := handlers.CreateUpdateDeleteCredentialsRequest(ctx, r.Log, r.Scheme, r.AuthConfig, r.Client, req); err != nil {
return "", err
}

@ -1115,13 +1115,7 @@ string
<th>Description</th>
</tr>
</thead>
<tbody><tr><td><p>&#34;managed&#34;</p></td>
<td><p>CredentialModeManaged represents the usage of short-lived tokens retrieved from a credential source.
This mode is similar to CredentialModeToken,but instead of having a user-configured credential source,
it is configured by the environment, for example the Cloud Credential Operator in OpenShift.
This mode is only supported for certain object storage types in certain runtime environments.</p>
</td>
</tr><tr><td><p>&#34;static&#34;</p></td>
<tbody><tr><td><p>&#34;static&#34;</p></td>
<td><p>CredentialModeStatic represents the usage of static, long-lived credentials stored in a Secret.
This is the default authentication mode and available for all supported object storage types.</p>
</td>
@ -1131,6 +1125,12 @@ In this mode the static configuration does not contain credentials needed for th
Instead, they are generated during runtime using a service, which allows for shorter-lived credentials and
much more granular control. This authentication mode is not supported for all object storage types.</p>
</td>
</tr><tr><td><p>&#34;token-cco&#34;</p></td>
<td><p>CredentialModeTokenCCO represents the usage of short-lived tokens retrieved from a credential source.
This mode is similar to CredentialModeToken, but instead of having a user-configured credential source,
it is configured by the environment and the operator relies on the Cloud Credential Operator to provide
a secret. This mode is only supported for certain object storage types in certain runtime environments.</p>
</td>
</tr></tbody>
</table>
@ -1779,10 +1779,6 @@ with the select cluster size.</p>
</tr><tr><td><p>&#34;InvalidTenantsConfiguration&#34;</p></td>
<td><p>ReasonInvalidTenantsConfiguration when the tenant configuration provided is invalid.</p>
</td>
</tr><tr><td><p>&#34;MissingCredentialsRequest&#34;</p></td>
<td><p>ReasonMissingCredentialsRequest when the required request for managed auth credentials to object
storage is missing.</p>
</td>
</tr><tr><td><p>&#34;MissingGatewayTenantAuthenticationConfig&#34;</p></td>
<td><p>ReasonMissingGatewayAuthenticationConfig when the config for when a tenant is missing authentication config</p>
</td>
@ -1797,10 +1793,6 @@ 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>
@ -1813,6 +1805,11 @@ storage is missing.</p>
<td><p>ReasonMissingRulerSecret when the required secret to authorization remote write connections
for the ruler is missing.</p>
</td>
</tr><tr><td><p>&#34;MissingTokenCCOAuthenticationSecret&#34;</p></td>
<td><p>ReasonMissingTokenCCOAuthSecret when the secret generated by CCO for token authentication is missing.
This is usually a transient error because the secret is not immediately available after creating the
CredentialsRequest, but it can persist if the CCO or its configuration are incorrect.</p>
</td>
</tr><tr><td><p>&#34;PendingComponents&#34;</p></td>
<td><p>ReasonPendingComponents when all/some LokiStack components pending dependencies</p>
</td>

@ -411,13 +411,13 @@ bool
</tr>
<tr>
<td>
<code>ManagedAuthEnv</code><br/>
<code>TokenCCOAuthEnv</code><br/>
<em>
bool
</em>
</td>
<td>
<p>ManagedAuthEnv is true when OpenShift-functions are enabled and the operator has detected
<p>TokenCCOAuthEnv is true when OpenShift-functions are enabled and the operator has detected
that it is running with some kind of &ldquo;workload identity&rdquo; (AWS STS, Azure WIF) enabled.</p>
</td>
</tr>

@ -37,7 +37,7 @@ readonly access_key_id
secret_access_key=${SECRET_ACCESS_KEY:-$(aws configure get aws_secret_access_key)}
readonly secret_access_key
# Managed authentication with/without a manually provisioned AWS Role.
# token authentication with/without a manually provisioned AWS Role.
readonly sts=${STS:-false}
readonly role_arn=${2-}

@ -13,12 +13,12 @@ type AzureEnvironment struct {
Region string
}
type ManagedAuthConfig struct {
type TokenCCOAuthConfig struct {
AWS *AWSEnvironment
Azure *AzureEnvironment
}
func discoverManagedAuthConfig() *ManagedAuthConfig {
func discoverTokenCCOAuthConfig() *TokenCCOAuthConfig {
// AWS
roleARN := os.Getenv("ROLEARN")
@ -30,13 +30,13 @@ func discoverManagedAuthConfig() *ManagedAuthConfig {
switch {
case roleARN != "":
return &ManagedAuthConfig{
return &TokenCCOAuthConfig{
AWS: &AWSEnvironment{
RoleARN: roleARN,
},
}
case clientID != "" && tenantID != "" && subscriptionID != "":
return &ManagedAuthConfig{
return &TokenCCOAuthConfig{
Azure: &AzureEnvironment{
ClientID: clientID,
SubscriptionID: subscriptionID,

@ -17,7 +17,7 @@ import (
// LoadConfig initializes the controller configuration, optionally overriding the defaults
// from a provided configuration file.
func LoadConfig(scheme *runtime.Scheme, configFile string) (*configv1.ProjectConfig, *ManagedAuthConfig, ctrl.Options, error) {
func LoadConfig(scheme *runtime.Scheme, configFile string) (*configv1.ProjectConfig, *TokenCCOAuthConfig, ctrl.Options, error) {
options := ctrl.Options{Scheme: scheme}
if configFile == "" {
return &configv1.ProjectConfig{}, nil, options, nil
@ -28,13 +28,13 @@ func LoadConfig(scheme *runtime.Scheme, configFile string) (*configv1.ProjectCon
return nil, nil, options, fmt.Errorf("failed to parse controller manager config file: %w", err)
}
managedAuth := discoverManagedAuthConfig()
if ctrlCfg.Gates.OpenShift.Enabled && managedAuth != nil {
ctrlCfg.Gates.OpenShift.ManagedAuthEnv = true
tokenCCOAuth := discoverTokenCCOAuthConfig()
if ctrlCfg.Gates.OpenShift.Enabled && tokenCCOAuth != nil {
ctrlCfg.Gates.OpenShift.TokenCCOAuthEnv = true
}
options = mergeOptionsFromFile(options, ctrlCfg)
return ctrlCfg, managedAuth, options, nil
return ctrlCfg, tokenCCOAuth, options, nil
}
func mergeOptionsFromFile(o manager.Options, cfg *configv1.ProjectConfig) manager.Options {

@ -22,7 +22,7 @@ import (
// CreateUpdateDeleteCredentialsRequest creates a new CredentialsRequest resource for a Lokistack
// to request a cloud credentials Secret resource from the OpenShift cloud-credentials-operator.
func CreateUpdateDeleteCredentialsRequest(ctx context.Context, log logr.Logger, scheme *runtime.Scheme, managedAuth *config.ManagedAuthConfig, k k8s.Client, req ctrl.Request) error {
func CreateUpdateDeleteCredentialsRequest(ctx context.Context, log logr.Logger, scheme *runtime.Scheme, tokenCCOAuth *config.TokenCCOAuthConfig, k k8s.Client, req ctrl.Request) error {
ll := log.WithValues("lokistack", req.NamespacedName, "event", "createCredentialsRequest")
var stack lokiv1.LokiStack
@ -59,7 +59,7 @@ func CreateUpdateDeleteCredentialsRequest(ctx context.Context, log logr.Logger,
LokiStackNamespace: stack.Namespace,
RulerName: manifests.RulerName(stack.Name),
},
ManagedAuth: managedAuth,
TokenCCOAuth: tokenCCOAuth,
}
credReq, err := openshift.BuildCredentialsRequest(opts)
@ -99,7 +99,7 @@ func hasManagedCredentialMode(stack *lokiv1.LokiStack) bool {
switch stack.Spec.Storage.Secret.CredentialMode {
case lokiv1.CredentialModeStatic, lokiv1.CredentialModeToken:
return false
case lokiv1.CredentialModeManaged:
case lokiv1.CredentialModeTokenCCO:
return true
default:
}

@ -57,13 +57,13 @@ func TestCreateUpdateDeleteCredentialsRequest_CreateNewResource(t *testing.T) {
NamespacedName: client.ObjectKey{Name: "my-stack", Namespace: "ns"},
}
managedAuth := &config.ManagedAuthConfig{
tokenCCOAuth := &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "a-role-arn",
},
}
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, managedAuth, k, req)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, tokenCCOAuth, k, req)
require.NoError(t, err)
require.Equal(t, 1, k.CreateCallCount())
@ -89,7 +89,7 @@ func TestCreateUpdateDeleteCredentialsRequest_CreateNewResourceAzure(t *testing.
NamespacedName: client.ObjectKey{Name: "my-stack", Namespace: "ns"},
}
managedAuth := &config.ManagedAuthConfig{
tokenCCOAuth := &config.TokenCCOAuthConfig{
Azure: &config.AzureEnvironment{
ClientID: "test-client-id",
SubscriptionID: "test-tenant-id",
@ -98,7 +98,7 @@ func TestCreateUpdateDeleteCredentialsRequest_CreateNewResourceAzure(t *testing.
},
}
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, managedAuth, k, req)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, tokenCCOAuth, k, req)
require.NoError(t, err)
require.Equal(t, 1, k.CreateCallCount())
@ -117,7 +117,7 @@ func TestCreateUpdateDeleteCredentialsRequest_Update_WhenCredentialsRequestExist
NamespacedName: client.ObjectKey{Name: "my-stack", Namespace: "ns"},
}
managedAuth := &config.ManagedAuthConfig{
tokenCCOAuth := &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "a-role-arn",
},
@ -138,7 +138,7 @@ func TestCreateUpdateDeleteCredentialsRequest_Update_WhenCredentialsRequestExist
k := credentialsRequestFakeClient(cr, lokistack)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, managedAuth, k, req)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, tokenCCOAuth, k, req)
require.NoError(t, err)
require.Equal(t, 2, k.GetCallCount())
require.Equal(t, 0, k.CreateCallCount())
@ -150,7 +150,7 @@ func TestCreateUpdateDeleteCredentialsRequest_DeleteExisting_WhenNotManagedMode(
NamespacedName: client.ObjectKey{Name: "my-stack", Namespace: "ns"},
}
managedAuth := &config.ManagedAuthConfig{
tokenCCOAuth := &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "a-role-arn",
},
@ -178,7 +178,7 @@ func TestCreateUpdateDeleteCredentialsRequest_DeleteExisting_WhenNotManagedMode(
k := credentialsRequestFakeClient(cr, lokistack)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, managedAuth, k, req)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, tokenCCOAuth, k, req)
require.NoError(t, err)
require.Equal(t, 2, k.GetCallCount())
require.Equal(t, 0, k.CreateCallCount())
@ -191,7 +191,7 @@ func TestCreateUpdateDeleteCredentialsRequest_DoNothing_WhenNotManagedMode(t *te
NamespacedName: client.ObjectKey{Name: "my-stack", Namespace: "ns"},
}
managedAuth := &config.ManagedAuthConfig{
tokenCCOAuth := &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "a-role-arn",
},
@ -213,7 +213,7 @@ func TestCreateUpdateDeleteCredentialsRequest_DoNothing_WhenNotManagedMode(t *te
k := credentialsRequestFakeClient(nil, lokistack)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, managedAuth, k, req)
err := CreateUpdateDeleteCredentialsRequest(context.Background(), logger, scheme, tokenCCOAuth, k, req)
require.NoError(t, err)
require.Equal(t, 2, k.GetCallCount())
require.Equal(t, 0, k.CreateCallCount())

@ -53,8 +53,8 @@ const gcpAccountTypeExternal = "external_account"
func getSecrets(ctx context.Context, k k8s.Client, stack *lokiv1.LokiStack, fg configv1.FeatureGates) (*corev1.Secret, *corev1.Secret, error) {
var (
storageSecret corev1.Secret
managedAuthSecret corev1.Secret
storageSecret corev1.Secret
tokenCCOAuthSecret corev1.Secret
)
key := client.ObjectKey{Name: stack.Spec.Storage.Secret.Name, Namespace: stack.Namespace}
@ -69,27 +69,27 @@ func getSecrets(ctx context.Context, k k8s.Client, stack *lokiv1.LokiStack, fg c
return nil, nil, fmt.Errorf("failed to lookup lokistack storage secret: %w", err)
}
if fg.OpenShift.ManagedAuthEnv {
if fg.OpenShift.TokenCCOAuthEnv {
secretName := storage.ManagedCredentialsSecretName(stack.Name)
managedAuthCredsKey := client.ObjectKey{Name: secretName, Namespace: stack.Namespace}
if err := k.Get(ctx, managedAuthCredsKey, &managedAuthSecret); err != nil {
tokenCCOAuthCredsKey := client.ObjectKey{Name: secretName, Namespace: stack.Namespace}
if err := k.Get(ctx, tokenCCOAuthCredsKey, &tokenCCOAuthSecret); err != nil {
if apierrors.IsNotFound(err) {
// We don't know if this is an error yet, need to wait for evaluation of CredentialMode
// For now we go with empty "managed secret", the eventual DegradedError will be returned later.
return &storageSecret, nil, nil
}
return nil, nil, fmt.Errorf("failed to lookup OpenShift CCO managed authentication credentials secret: %w", err)
return nil, nil, fmt.Errorf("failed to lookup OpenShift CCO token authentication credentials secret: %w", err)
}
return &storageSecret, &managedAuthSecret, nil
return &storageSecret, &tokenCCOAuthSecret, nil
}
return &storageSecret, nil, nil
}
// extractSecrets reads the k8s obj storage secret into a manifest object storage struct if valid.
// The managed auth is also read into the manifest object under the right circumstances.
func extractSecrets(secretSpec lokiv1.ObjectStorageSecretSpec, objStore, managedAuth *corev1.Secret, fg configv1.FeatureGates) (storage.Options, error) {
// The token cco auth is also read into the manifest object under the right circumstances.
func extractSecrets(secretSpec lokiv1.ObjectStorageSecretSpec, objStore, tokenCCOAuth *corev1.Secret, fg configv1.FeatureGates) (storage.Options, error) {
hash, err := hashSecretData(objStore)
if err != nil {
return storage.Options{}, errSecretHashError
@ -98,16 +98,16 @@ func extractSecrets(secretSpec lokiv1.ObjectStorageSecretSpec, objStore, managed
openShiftOpts := storage.OpenShiftOptions{
Enabled: fg.OpenShift.Enabled,
}
if managedAuth != nil {
var managedAuthHash string
managedAuthHash, err = hashSecretData(managedAuth)
if tokenCCOAuth != nil {
var tokenCCOAuthHash string
tokenCCOAuthHash, err = hashSecretData(tokenCCOAuth)
if err != nil {
return storage.Options{}, errSecretHashError
}
openShiftOpts.CloudCredentials = storage.CloudCredentials{
SecretName: managedAuth.Name,
SHA1: managedAuthHash,
SecretName: tokenCCOAuth.Name,
SHA1: tokenCCOAuthHash,
}
}
@ -161,9 +161,9 @@ func determineCredentialMode(spec lokiv1.ObjectStorageSecretSpec, secret *corev1
return spec.CredentialMode, nil
}
if fg.OpenShift.ManagedAuthEnv {
// Default to managed credential mode on a managed-auth installation
return lokiv1.CredentialModeManaged, nil
if fg.OpenShift.TokenCCOAuthEnv {
// Default to token cco credential mode on a token-cco-auth installation
return lokiv1.CredentialModeTokenCCO, nil
}
switch spec.Type {
@ -298,7 +298,7 @@ func validateAzureCredentials(s *corev1.Secret, credentialMode lokiv1.Credential
}
return true, nil
case lokiv1.CredentialModeManaged:
case lokiv1.CredentialModeTokenCCO:
if len(accountKey) > 0 || len(clientID) > 0 || len(tenantID) > 0 || len(subscriptionID) > 0 {
return false, errAzureManagedIdentityNoOverride
}
@ -370,7 +370,7 @@ func extractGCSConfigSecret(s *corev1.Secret, credentialMode lokiv1.CredentialMo
WorkloadIdentity: true,
Audience: audience,
}, nil
case lokiv1.CredentialModeManaged:
case lokiv1.CredentialModeTokenCCO:
return nil, fmt.Errorf("%w: type: %s credentialMode: %s", errSecretUnsupportedCredentialMode, lokiv1.ObjectStorageSecretGCS, credentialMode)
default:
}
@ -409,7 +409,7 @@ func extractS3ConfigSecret(s *corev1.Secret, credentialMode lokiv1.CredentialMod
}
switch credentialMode {
case lokiv1.CredentialModeManaged:
case lokiv1.CredentialModeTokenCCO:
cfg.STS = true
cfg.Audience = string(audience)
// Do not allow users overriding the role arn provided on Loki Operator installation

@ -143,7 +143,7 @@ func TestAzureExtract(t *testing.T) {
wantError: "missing secret field: subscription_id",
},
{
name: "managed auth - no auth override",
name: "token cco auth - no auth override",
secret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "test"},
Data: map[string][]byte{
@ -159,8 +159,8 @@ func TestAzureExtract(t *testing.T) {
},
featureGates: configv1.FeatureGates{
OpenShift: configv1.OpenShiftFeatureGates{
Enabled: true,
ManagedAuthEnv: true,
Enabled: true,
TokenCCOAuthEnv: true,
},
},
wantError: errAzureManagedIdentityNoOverride.Error(),
@ -231,11 +231,11 @@ func TestAzureExtract(t *testing.T) {
},
featureGates: configv1.FeatureGates{
OpenShift: configv1.OpenShiftFeatureGates{
Enabled: true,
ManagedAuthEnv: true,
Enabled: true,
TokenCCOAuthEnv: true,
},
},
wantCredentialMode: lokiv1.CredentialModeManaged,
wantCredentialMode: lokiv1.CredentialModeTokenCCO,
},
{
name: "all set including optional",
@ -554,25 +554,25 @@ func TestS3Extract(t *testing.T) {
}
}
func TestS3Extract_WithOpenShiftManagedAuth(t *testing.T) {
func TestS3Extract_WithOpenShiftTokenCCOAuth(t *testing.T) {
fg := configv1.FeatureGates{
OpenShift: configv1.OpenShiftFeatureGates{
Enabled: true,
ManagedAuthEnv: true,
Enabled: true,
TokenCCOAuthEnv: true,
},
}
type test struct {
name string
secret *corev1.Secret
managedAuthSecret *corev1.Secret
wantError string
name string
secret *corev1.Secret
tokenCCOAuthSecret *corev1.Secret
wantError string
}
table := []test{
{
name: "missing bucketnames",
secret: &corev1.Secret{},
managedAuthSecret: &corev1.Secret{},
wantError: "missing secret field: bucketnames",
name: "missing bucketnames",
secret: &corev1.Secret{},
tokenCCOAuthSecret: &corev1.Secret{},
wantError: "missing secret field: bucketnames",
},
{
name: "missing region",
@ -581,8 +581,8 @@ func TestS3Extract_WithOpenShiftManagedAuth(t *testing.T) {
"bucketnames": []byte("this,that"),
},
},
managedAuthSecret: &corev1.Secret{},
wantError: "missing secret field: region",
tokenCCOAuthSecret: &corev1.Secret{},
wantError: "missing secret field: region",
},
{
name: "override role_arn not allowed",
@ -593,8 +593,8 @@ func TestS3Extract_WithOpenShiftManagedAuth(t *testing.T) {
"role_arn": []byte("role-arn"),
},
},
managedAuthSecret: &corev1.Secret{},
wantError: "secret field not allowed: role_arn",
tokenCCOAuthSecret: &corev1.Secret{},
wantError: "secret field not allowed: role_arn",
},
{
name: "STS all set",
@ -605,8 +605,8 @@ func TestS3Extract_WithOpenShiftManagedAuth(t *testing.T) {
"region": []byte("a-region"),
},
},
managedAuthSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "managed-auth"},
tokenCCOAuthSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: "token-cco-auth"},
},
},
}
@ -619,16 +619,16 @@ func TestS3Extract_WithOpenShiftManagedAuth(t *testing.T) {
Type: lokiv1.ObjectStorageSecretS3,
}
opts, err := extractSecrets(spec, tst.secret, tst.managedAuthSecret, fg)
opts, err := extractSecrets(spec, tst.secret, tst.tokenCCOAuthSecret, fg)
if tst.wantError == "" {
require.NoError(t, err)
require.NotEmpty(t, opts.SecretName)
require.NotEmpty(t, opts.SecretSHA1)
require.Equal(t, lokiv1.ObjectStorageSecretS3, opts.SharedStore)
require.True(t, opts.S3.STS)
require.Equal(t, tst.managedAuthSecret.Name, opts.OpenShift.CloudCredentials.SecretName)
require.Equal(t, tst.tokenCCOAuthSecret.Name, opts.OpenShift.CloudCredentials.SecretName)
require.NotEmpty(t, opts.OpenShift.CloudCredentials.SHA1)
require.Equal(t, lokiv1.CredentialModeManaged, opts.CredentialMode)
require.Equal(t, lokiv1.CredentialModeTokenCCO, opts.CredentialMode)
} else {
require.EqualError(t, err, tst.wantError)
}

@ -20,14 +20,14 @@ import (
// - The object storage schema config is invalid.
// - The object storage CA ConfigMap is missing if one referenced.
// - The object storage CA ConfigMap data is invalid.
// - The object storage managed auth secret is missing (Only on OpenShift STS-clusters)
// - The object storage token cco auth secret is missing (Only on OpenShift STS-clusters)
func BuildOptions(ctx context.Context, k k8s.Client, stack *lokiv1.LokiStack, fg configv1.FeatureGates) (storage.Options, error) {
storageSecret, managedAuthSecret, err := getSecrets(ctx, k, stack, fg)
storageSecret, tokenCCOAuthSecret, err := getSecrets(ctx, k, stack, fg)
if err != nil {
return storage.Options{}, err
}
objStore, err := extractSecrets(stack.Spec.Storage.Secret, storageSecret, managedAuthSecret, fg)
objStore, err := extractSecrets(stack.Spec.Storage.Secret, storageSecret, tokenCCOAuthSecret, fg)
if err != nil {
return storage.Options{}, &status.DegradedError{
Message: fmt.Sprintf("Invalid object storage secret contents: %s", err),
@ -36,11 +36,11 @@ func BuildOptions(ctx context.Context, k k8s.Client, stack *lokiv1.LokiStack, fg
}
}
if objStore.CredentialMode == lokiv1.CredentialModeManaged && managedAuthSecret == nil {
// If we have no managed-auth secret at this point, it is an error
if objStore.CredentialMode == lokiv1.CredentialModeTokenCCO && tokenCCOAuthSecret == nil {
// If we have no token cco auth secret at this point, it is an error
return storage.Options{}, &status.DegradedError{
Message: "Missing OpenShift cloud credentials secret",
Reason: lokiv1.ReasonMissingManagedAuthSecret,
Reason: lokiv1.ReasonMissingTokenCCOAuthSecret,
Requeue: true,
}
}

@ -47,7 +47,7 @@ var (
},
}
defaultManagedAuthSecret = corev1.Secret{
defaultTokenCCOAuthSecret = corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "some-stack-secret",
Namespace: "some-ns",
@ -147,13 +147,13 @@ func TestBuildOptions_WhenMissingCloudCredentialsSecret_SetDegraded(t *testing.T
fg := configv1.FeatureGates{
OpenShift: configv1.OpenShiftFeatureGates{
ManagedAuthEnv: true,
TokenCCOAuthEnv: true,
},
}
degradedErr := &status.DegradedError{
Message: "Missing OpenShift cloud credentials secret",
Reason: lokiv1.ReasonMissingManagedAuthSecret,
Reason: lokiv1.ReasonMissingTokenCCOAuthSecret,
Requeue: true,
}
@ -176,7 +176,7 @@ func TestBuildOptions_WhenMissingCloudCredentialsSecret_SetDegraded(t *testing.T
},
},
Secret: lokiv1.ObjectStorageSecretSpec{
Name: defaultManagedAuthSecret.Name,
Name: defaultTokenCCOAuthSecret.Name,
Type: lokiv1.ObjectStorageSecretS3,
},
},
@ -189,8 +189,8 @@ func TestBuildOptions_WhenMissingCloudCredentialsSecret_SetDegraded(t *testing.T
k.SetClientObject(object, stack)
return nil
}
if name.Name == defaultManagedAuthSecret.Name {
k.SetClientObject(object, &defaultManagedAuthSecret)
if name.Name == defaultTokenCCOAuthSecret.Name {
k.SetClientObject(object, &defaultTokenCCOAuthSecret)
return nil
}
if name.Name == fmt.Sprintf("%s-aws-creds", stack.Name) {

@ -17,7 +17,7 @@ const azureFallbackRegion = "centralus"
func BuildCredentialsRequest(opts Options) (*cloudcredentialv1.CredentialsRequest, error) {
stack := client.ObjectKey{Name: opts.BuildOpts.LokiStackName, Namespace: opts.BuildOpts.LokiStackNamespace}
providerSpec, err := encodeProviderSpec(opts.ManagedAuth)
providerSpec, err := encodeProviderSpec(opts.TokenCCOAuth)
if err != nil {
return nil, kverrors.Wrap(err, "failed encoding credentialsrequest provider spec")
}
@ -42,7 +42,7 @@ func BuildCredentialsRequest(opts Options) (*cloudcredentialv1.CredentialsReques
}, nil
}
func encodeProviderSpec(env *config.ManagedAuthConfig) (*runtime.RawExtension, error) {
func encodeProviderSpec(env *config.TokenCCOAuthConfig) (*runtime.RawExtension, error) {
var spec runtime.Object
switch {

@ -15,7 +15,7 @@ func TestBuildCredentialsRequest_HasSecretRef_MatchingLokiStackNamespace(t *test
LokiStackName: "a-stack",
LokiStackNamespace: "ns",
},
ManagedAuth: &config.ManagedAuthConfig{
TokenCCOAuth: &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "role-arn",
},
@ -33,7 +33,7 @@ func TestBuildCredentialsRequest_HasServiceAccountNames_ContainsAllLokiStackServ
LokiStackName: "a-stack",
LokiStackNamespace: "ns",
},
ManagedAuth: &config.ManagedAuthConfig{
TokenCCOAuth: &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "role-arn",
},
@ -52,7 +52,7 @@ func TestBuildCredentialsRequest_CloudTokenPath_MatchinOpenShiftSADirectory(t *t
LokiStackName: "a-stack",
LokiStackNamespace: "ns",
},
ManagedAuth: &config.ManagedAuthConfig{
TokenCCOAuth: &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "role-arn",
},
@ -78,7 +78,7 @@ func TestBuildCredentialsRequest_FollowsNamingConventions(t *testing.T) {
LokiStackName: "a-stack",
LokiStackNamespace: "ns",
},
ManagedAuth: &config.ManagedAuthConfig{
TokenCCOAuth: &config.TokenCCOAuthConfig{
AWS: &config.AWSEnvironment{
RoleARN: "role-arn",
},

@ -15,7 +15,7 @@ type Options struct {
BuildOpts BuildOptions
Authentication []AuthenticationSpec
Authorization AuthorizationSpec
ManagedAuth *config.ManagedAuthConfig
TokenCCOAuth *config.TokenCCOAuthConfig
}
// AuthenticationSpec describes the authentication specification

@ -14,9 +14,9 @@ import (
)
var (
managedAuthConfigVolumeMount = corev1.VolumeMount{
Name: managedAuthConfigVolumeName,
MountPath: managedAuthConfigDirectory,
tokenCCOAuthConfigVolumeMount = corev1.VolumeMount{
Name: tokenAuthConfigVolumeName,
MountPath: tokenAuthConfigDirectory,
}
saTokenVolumeMount = corev1.VolumeMount{
@ -136,14 +136,14 @@ func ensureObjectStoreCredentials(p *corev1.PodSpec, opts Options) corev1.PodSpe
MountPath: secretDirectory,
})
if managedAuthEnabled(opts) {
container.Env = append(container.Env, managedAuthCredentials(opts)...)
if tokenAuthEnabled(opts) {
container.Env = append(container.Env, tokenAuthCredentials(opts)...)
volumes = append(volumes, saTokenVolume(opts))
container.VolumeMounts = append(container.VolumeMounts, saTokenVolumeMount)
if opts.OpenShift.ManagedAuthEnabled() && opts.S3 != nil && opts.S3.STS {
volumes = append(volumes, managedAuthConfigVolume(opts))
container.VolumeMounts = append(container.VolumeMounts, managedAuthConfigVolumeMount)
if opts.OpenShift.TokenCCOAuthEnabled() && opts.S3 != nil && opts.S3.STS {
volumes = append(volumes, tokenCCOAuthConfigVolume(opts))
container.VolumeMounts = append(container.VolumeMounts, tokenCCOAuthConfigVolumeMount)
}
} else {
container.Env = append(container.Env, staticAuthCredentials(opts)...)
@ -190,12 +190,12 @@ func staticAuthCredentials(opts Options) []corev1.EnvVar {
}
}
func managedAuthCredentials(opts Options) []corev1.EnvVar {
func tokenAuthCredentials(opts Options) []corev1.EnvVar {
switch opts.SharedStore {
case lokiv1.ObjectStorageSecretS3:
if opts.OpenShift.ManagedAuthEnabled() {
if opts.OpenShift.TokenCCOAuthEnabled() {
return []corev1.EnvVar{
envVarFromValue(EnvAWSCredentialsFile, path.Join(managedAuthConfigDirectory, KeyAWSCredentialsFilename)),
envVarFromValue(EnvAWSCredentialsFile, path.Join(tokenAuthConfigDirectory, KeyAWSCredentialsFilename)),
envVarFromValue(EnvAWSSdkLoadConfig, "true"),
}
} else {
@ -205,7 +205,7 @@ func managedAuthCredentials(opts Options) []corev1.EnvVar {
}
}
case lokiv1.ObjectStorageSecretAzure:
if opts.OpenShift.ManagedAuthEnabled() {
if opts.OpenShift.TokenCCOAuthEnabled() {
return []corev1.EnvVar{
envVarFromSecret(EnvAzureStorageAccountName, opts.SecretName, KeyAzureStorageAccountName),
envVarFromSecret(EnvAzureClientID, opts.OpenShift.CloudCredentials.SecretName, azureManagedCredentialKeyClientID),
@ -300,9 +300,9 @@ func envVarFromValue(name, value string) corev1.EnvVar {
}
}
func managedAuthEnabled(opts Options) bool {
func tokenAuthEnabled(opts Options) bool {
switch opts.CredentialMode {
case lokiv1.CredentialModeToken, lokiv1.CredentialModeManaged:
case lokiv1.CredentialModeToken, lokiv1.CredentialModeTokenCCO:
return true
case lokiv1.CredentialModeStatic:
fallthrough
@ -346,9 +346,9 @@ func saTokenVolume(opts Options) corev1.Volume {
}
}
func managedAuthConfigVolume(opts Options) corev1.Volume {
func tokenCCOAuthConfigVolume(opts Options) corev1.Volume {
return corev1.Volume{
Name: managedAuthConfigVolumeName,
Name: tokenAuthConfigVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: opts.OpenShift.CloudCredentials.SecretName,

@ -424,7 +424,7 @@ func TestConfigureDeploymentForStorageType(t *testing.T) {
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretAzure,
CredentialMode: lokiv1.CredentialModeManaged,
CredentialMode: lokiv1.CredentialModeTokenCCO,
Azure: &AzureStorageConfig{
WorkloadIdentity: true,
},
@ -861,7 +861,7 @@ func TestConfigureDeploymentForStorageType(t *testing.T) {
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretS3,
CredentialMode: lokiv1.CredentialModeManaged,
CredentialMode: lokiv1.CredentialModeTokenCCO,
S3: &S3StorageConfig{
STS: true,
},
@ -904,12 +904,12 @@ func TestConfigureDeploymentForStorageType(t *testing.T) {
ReadOnly: false,
MountPath: saTokenVolumeMountPath,
},
managedAuthConfigVolumeMount,
tokenCCOAuthConfigVolumeMount,
},
Env: []corev1.EnvVar{
{
Name: "AWS_SHARED_CREDENTIALS_FILE",
Value: "/etc/storage/managed-auth/credentials",
Value: "/etc/storage/token-auth/credentials",
},
{
Name: "AWS_SDK_LOAD_CONFIG",
@ -944,7 +944,7 @@ func TestConfigureDeploymentForStorageType(t *testing.T) {
},
},
{
Name: managedAuthConfigVolumeName,
Name: tokenAuthConfigVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: "cloud-credentials",
@ -1623,7 +1623,7 @@ func TestConfigureStatefulSetForStorageType(t *testing.T) {
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretAzure,
CredentialMode: lokiv1.CredentialModeManaged,
CredentialMode: lokiv1.CredentialModeTokenCCO,
Azure: &AzureStorageConfig{
WorkloadIdentity: true,
},
@ -1811,7 +1811,7 @@ func TestConfigureStatefulSetForStorageType(t *testing.T) {
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretGCS,
CredentialMode: lokiv1.CredentialModeManaged,
CredentialMode: lokiv1.CredentialModeTokenCCO,
GCS: &GCSStorageConfig{
Audience: "test",
WorkloadIdentity: true,
@ -1967,7 +1967,7 @@ func TestConfigureStatefulSetForStorageType(t *testing.T) {
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretS3,
CredentialMode: lokiv1.CredentialModeManaged,
CredentialMode: lokiv1.CredentialModeTokenCCO,
S3: &S3StorageConfig{
STS: true,
},
@ -2010,12 +2010,12 @@ func TestConfigureStatefulSetForStorageType(t *testing.T) {
ReadOnly: false,
MountPath: saTokenVolumeMountPath,
},
managedAuthConfigVolumeMount,
tokenCCOAuthConfigVolumeMount,
},
Env: []corev1.EnvVar{
{
Name: "AWS_SHARED_CREDENTIALS_FILE",
Value: "/etc/storage/managed-auth/credentials",
Value: "/etc/storage/token-auth/credentials",
},
{
Name: "AWS_SDK_LOAD_CONFIG",
@ -2050,7 +2050,7 @@ func TestConfigureStatefulSetForStorageType(t *testing.T) {
},
},
{
Name: managedAuthConfigVolumeName,
Name: tokenAuthConfigVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: "cloud-credentials",

@ -102,6 +102,6 @@ type CloudCredentials struct {
SHA1 string
}
func (o OpenShiftOptions) ManagedAuthEnabled() bool {
func (o OpenShiftOptions) TokenCCOAuthEnabled() bool {
return o.CloudCredentials.SecretName != "" && o.CloudCredentials.SHA1 != ""
}

@ -137,8 +137,8 @@ const (
storageTLSVolume = "storage-tls"
caDirectory = "/etc/storage/ca"
managedAuthConfigVolumeName = "managed-auth-config"
managedAuthConfigDirectory = "/etc/storage/managed-auth"
tokenAuthConfigVolumeName = "token-auth-config"
tokenAuthConfigDirectory = "/etc/storage/token-auth"
awsDefaultAudience = "sts.amazonaws.com"

@ -78,8 +78,8 @@ const (
AnnotationLokiConfigHash string = "loki.grafana.com/config-hash"
// AnnotationLokiObjectStoreHash stores the last SHA1 hash of the loki object storage credetials.
AnnotationLokiObjectStoreHash string = "loki.grafana.com/object-store-hash"
// AnnotationLokiManagedAuthHash stores the last SHA1 hash of the loki managed auth credentials.
AnnotationLokiManagedAuthHash string = "loki.grafana.com/managed-auth-hash"
// AnnotationLokiTokenCCOAuthHash stores the SHA1 hash of the secret generated by the Cloud Credential Operator.
AnnotationLokiTokenCCOAuthHash string = "loki.grafana.com/token-cco-auth-hash"
// LabelCompactorComponent is the label value for the compactor component
LabelCompactorComponent string = "compactor"
@ -145,7 +145,7 @@ func commonAnnotations(opts Options) map[string]string {
a[AnnotationLokiObjectStoreHash] = opts.ObjectStorage.SecretSHA1
}
if opts.ObjectStorage.OpenShift.CloudCredentials.SHA1 != "" {
a[AnnotationLokiManagedAuthHash] = opts.ObjectStorage.OpenShift.CloudCredentials.SHA1
a[AnnotationLokiTokenCCOAuthHash] = opts.ObjectStorage.OpenShift.CloudCredentials.SHA1
}
return a

@ -59,14 +59,14 @@ func main() {
var err error
ctrlCfg, managedAuth, options, err := config.LoadConfig(scheme, configFile)
ctrlCfg, tokenCCOAuth, options, err := config.LoadConfig(scheme, configFile)
if err != nil {
logger.Error(err, "failed to load operator configuration")
os.Exit(1)
}
if managedAuth != nil {
logger.Info("Discovered OpenShift Cluster within a managed authentication environment")
if tokenCCOAuth != nil {
logger.Info("Discovered OpenShift Cluster within a token cco authentication environment")
}
if ctrlCfg.Gates.LokiStackAlerts && !ctrlCfg.Gates.ServiceMonitors {
@ -103,7 +103,7 @@ func main() {
Log: logger.WithName("controllers").WithName("lokistack"),
Scheme: mgr.GetScheme(),
FeatureGates: ctrlCfg.Gates,
AuthConfig: managedAuth,
AuthConfig: tokenCCOAuth,
}).SetupWithManager(mgr); err != nil {
logger.Error(err, "unable to create controller", "controller", "lokistack")
os.Exit(1)

Loading…
Cancel
Save