...

Source file src/edge-infra.dev/pkg/edge/api/services/cluster_config_service.go

Documentation: edge-infra.dev/pkg/edge/api/services

     1  package services
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  	"fmt"
     8  	"regexp"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"slices"
    13  
    14  	"github.com/google/uuid"
    15  	"github.com/hashicorp/go-multierror"
    16  
    17  	sqlerr "edge-infra.dev/pkg/edge/api/apierror/sql"
    18  	"edge-infra.dev/pkg/edge/api/graph/mapper"
    19  	"edge-infra.dev/pkg/edge/api/graph/model"
    20  	sqlquery "edge-infra.dev/pkg/edge/api/sql"
    21  	"edge-infra.dev/pkg/edge/constants"
    22  	linkerd "edge-infra.dev/pkg/edge/linkerd"
    23  	"edge-infra.dev/pkg/lib/fog"
    24  	"edge-infra.dev/pkg/sds/ien/topology"
    25  )
    26  
    27  const (
    28  	// config_key as expected in the db
    29  	AcRelayKey                    = "ac_relay"
    30  	PxeEnabledKey                 = "pxe_enabled"
    31  	BootstrapAckKey               = "bootstrap_ack"
    32  	VpnEnabledKey                 = "vpn_enabled"
    33  	ThickPosKey                   = "thick_pos"
    34  	EgressGatewayEnabledKey       = "egress_gateway_enabled"
    35  	GatewayRateLimitingEnabledKey = "gateway_rate_limiting_enabled"
    36  	UplinkRateLimitKey            = "uplink_rate_limit"
    37  	DownlinkRateLimitKey          = "downlink_rate_limit"
    38  	ClusterLogLevelKey            = "cluster_log_level"
    39  	NamespaceLogLevelsKey         = "namespace_log_levels"
    40  	AutoUpdateEnabledKey          = "auto_update_enabled"
    41  	MaximumLanOutageHoursKey      = "maximum_lan_outage_hours"
    42  	VncReadWriteAuthRequired      = "vnc_read_write_auth_required"
    43  	VncReadAuthRequired           = "vnc_read_auth_required"
    44  )
    45  
    46  var validClusterLogLevels = []string{
    47  	"DEBUG",
    48  	"INFO",
    49  	"NOTICE",
    50  	"WARNING",
    51  	"ERROR",
    52  	"CRITICAL",
    53  	"ALERT",
    54  	"EMERGENCY",
    55  }
    56  
    57  var (
    58  	// default values
    59  	defaultRateLimit = "100mbit"
    60  	logLevelDefault  = "ERROR"
    61  )
    62  
    63  var (
    64  	ErrInvalidRateLimit             = errors.New("invalid format for upload or download rate limits")
    65  	ErrClusterEdgeIDEmpty           = errors.New("cluster edge id cannot be empty")
    66  	ErrInvalidMaximumLanOutageHours = errors.New("maximum lan outage duration must be at least 24 hours")
    67  )
    68  
    69  type ErrInvalidLogLevel struct {
    70  	LogLevel string
    71  }
    72  
    73  func (e *ErrInvalidLogLevel) Error() string {
    74  	return fmt.Sprintf("%s is invalid log level. Valid log levels: %s", e.LogLevel, strings.Join(validClusterLogLevels, ","))
    75  }
    76  
    77  //go:generate mockgen -destination=../mocks/mock_cluster_config_service.go -package=mocks edge-infra.dev/pkg/edge/api/services ClusterConfigService
    78  type ClusterConfigService interface {
    79  	UpdateClusterConfig(ctx context.Context, clusterEdgeID string, updatedClusterConfig *model.UpdateClusterConfig) (*model.ClusterConfig, error)
    80  	GetClusterConfig(ctx context.Context, clusterEdgeID string) (*model.ClusterConfig, error)
    81  }
    82  
    83  type clusterConfigService struct {
    84  	SQLDB *sql.DB
    85  }
    86  
    87  func NewClusterConfigService(sqlDB *sql.DB) *clusterConfigService { //nolint:revive
    88  	return &clusterConfigService{
    89  		SQLDB: sqlDB,
    90  	}
    91  }
    92  
    93  func (c *clusterConfigService) UpdateClusterConfig(ctx context.Context, clusterEdgeID string, inputCfg *model.UpdateClusterConfig) (*model.ClusterConfig, error) {
    94  	clusterCfg, err := c.GetClusterConfig(ctx, clusterEdgeID)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	// overrides current configuration with new configuration
   100  	mapUpdateClusterConfig(clusterCfg, inputCfg)
   101  
   102  	// validate updated cluster config
   103  	if err := validateClusterConfig(clusterCfg); err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	// convert values to map[string]string
   108  	clusterCfgValues, err := mapUpdateClusterConfigAttributes(inputCfg)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	return clusterCfg, c.upsertClusterConfigKeys(ctx, clusterEdgeID, clusterCfgValues)
   113  }
   114  
   115  func (c *clusterConfigService) GetClusterConfig(ctx context.Context, clusterEdgeID string) (*model.ClusterConfig, error) {
   116  	if clusterEdgeID == "" {
   117  		return nil, ErrClusterEdgeIDEmpty
   118  	}
   119  
   120  	rows, err := c.SQLDB.QueryContext(ctx, sqlquery.GetClusterConfig, clusterEdgeID)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	defer rows.Close()
   125  
   126  	return scanClusterConfigRows(clusterEdgeID, rows)
   127  }
   128  
   129  // iterates through each key, value and executes an upsert operation on cluster_config table
   130  func (c *clusterConfigService) upsertClusterConfigKeys(ctx context.Context, clusterEdgeID string, clusterCfg map[string]string) error {
   131  	transaction, err := c.SQLDB.BeginTx(ctx, nil)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	for key, value := range clusterCfg {
   137  		err = queryClusterConfig(ctx, transaction, sqlquery.UpdateClusterConfig, clusterEdgeID, key, value)
   138  		if err != nil {
   139  			return err
   140  		}
   141  	}
   142  
   143  	return transaction.Commit()
   144  }
   145  
   146  func queryClusterConfig(ctx context.Context, transaction *sql.Tx, query string, clusterID, key, val string) error {
   147  	if _, err := transaction.ExecContext(ctx, query, clusterID, key, val, uuid.NewString()); err != nil {
   148  		if rollbackErr := transaction.Rollback(); rollbackErr != nil {
   149  			return multierror.Append(err, rollbackErr)
   150  		}
   151  		return err
   152  	}
   153  	return nil
   154  }
   155  
   156  func mapUpdateClusterConfigAttributes(updateClusterConfig *model.UpdateClusterConfig) (map[string]string, error) {
   157  	output := map[string]string{}
   158  
   159  	if updateClusterConfig.AcRelay != nil {
   160  		output[AcRelayKey] = strconv.FormatBool(*updateClusterConfig.AcRelay)
   161  	}
   162  
   163  	if updateClusterConfig.PxeEnabled != nil {
   164  		output[PxeEnabledKey] = strconv.FormatBool(*updateClusterConfig.PxeEnabled)
   165  	}
   166  
   167  	if updateClusterConfig.BootstrapAck != nil {
   168  		output[BootstrapAckKey] = strconv.FormatBool(*updateClusterConfig.BootstrapAck)
   169  	}
   170  
   171  	if updateClusterConfig.VpnEnabled != nil {
   172  		output[VpnEnabledKey] = strconv.FormatBool(*updateClusterConfig.VpnEnabled)
   173  	}
   174  
   175  	if updateClusterConfig.ThickPos != nil {
   176  		output[ThickPosKey] = strconv.FormatBool(*updateClusterConfig.ThickPos)
   177  	}
   178  
   179  	if updateClusterConfig.EgressGatewayEnabled != nil {
   180  		output[EgressGatewayEnabledKey] = strconv.FormatBool(*updateClusterConfig.EgressGatewayEnabled)
   181  	}
   182  
   183  	if updateClusterConfig.GatewayRateLimitingEnabled != nil {
   184  		output[GatewayRateLimitingEnabledKey] = strconv.FormatBool(*updateClusterConfig.GatewayRateLimitingEnabled)
   185  	}
   186  
   187  	if updateClusterConfig.UplinkRateLimit != nil {
   188  		output[UplinkRateLimitKey] = *updateClusterConfig.UplinkRateLimit
   189  	}
   190  
   191  	if updateClusterConfig.DownlinkRateLimit != nil {
   192  		output[DownlinkRateLimitKey] = *updateClusterConfig.DownlinkRateLimit
   193  	}
   194  
   195  	if updateClusterConfig.ClusterLogLevel != nil {
   196  		output[ClusterLogLevelKey] = *updateClusterConfig.ClusterLogLevel
   197  	}
   198  
   199  	if updateClusterConfig.NamespaceLogLevels != nil {
   200  		namespaceLogLevelsJSONStr, err := mapper.NLLPToJSON(updateClusterConfig.NamespaceLogLevels)
   201  		if err != nil {
   202  			return nil, fmt.Errorf("Error when marshaling to a string in mapUpdatedClusterConfigAttributes: %s", err)
   203  		}
   204  
   205  		output[NamespaceLogLevelsKey] = namespaceLogLevelsJSONStr
   206  	}
   207  
   208  	if updateClusterConfig.MaximumLanOutageHours != nil {
   209  		output[MaximumLanOutageHoursKey] = strconv.FormatInt(int64(*updateClusterConfig.MaximumLanOutageHours), 10)
   210  	}
   211  
   212  	// TODO: Marked as DEPRECATED. Remove when appropriate
   213  	//nolint:staticcheck // Allow existing usage of deprecated fields
   214  	if updateClusterConfig.LinkerdIdentityIssuerCertDuration != nil {
   215  		output[constants.LinkerdIdentityIssuerCertDuration] = strconv.FormatInt(int64(*updateClusterConfig.LinkerdIdentityIssuerCertDuration), 10)
   216  	}
   217  	// TODO: Marked as DEPRECATED. Remove when appropriate
   218  	//nolint:staticcheck // Allow existing usage of deprecated fields
   219  	if updateClusterConfig.LinkerdIdentityIssuerCertRenewBefore != nil {
   220  		output[constants.LinkerdIdentityIssuerCertRenewBefore] = strconv.FormatInt(int64(*updateClusterConfig.LinkerdIdentityIssuerCertRenewBefore), 10)
   221  	}
   222  
   223  	if updateClusterConfig.AutoUpdateEnabled != nil {
   224  		output[AutoUpdateEnabledKey] = strconv.FormatBool(*updateClusterConfig.AutoUpdateEnabled)
   225  	}
   226  
   227  	if updateClusterConfig.VncReadWriteAuthRequired != nil {
   228  		output[VncReadWriteAuthRequired] = strconv.FormatBool(*updateClusterConfig.VncReadWriteAuthRequired)
   229  	}
   230  
   231  	if updateClusterConfig.VncReadAuthRequired != nil {
   232  		output[VncReadAuthRequired] = strconv.FormatBool(*updateClusterConfig.VncReadAuthRequired)
   233  	}
   234  
   235  	return output, nil
   236  }
   237  
   238  func scanClusterConfigRows(clusterEdgeID string, rows *sql.Rows) (*model.ClusterConfig, error) {
   239  	clusterConfig := defaultClusterConfig(clusterEdgeID)
   240  
   241  	for rows.Next() {
   242  		var clusterConfigEdgeID, configKey, configValue string
   243  		if err := rows.Scan(&clusterConfigEdgeID, &clusterConfig.ClusterEdgeID, &configKey, &configValue); err != nil {
   244  			return nil, err
   245  		}
   246  		err := insertValueIntoClusterConfig(clusterConfig, configKey, configValue)
   247  		if err != nil {
   248  			return nil, err
   249  		}
   250  	}
   251  	if err := rows.Err(); err != nil {
   252  		return nil, sqlerr.Wrap(err)
   253  	}
   254  
   255  	return clusterConfig, nil
   256  }
   257  
   258  // Update a specific key in the cluster config with the given value
   259  func insertValueIntoClusterConfig(clusterConfig *model.ClusterConfig, configKey, configValue string) error { //nolint:gocyclo // Each config option follows a consistent pattern
   260  	var err error
   261  	switch configKey {
   262  	case AcRelayKey:
   263  		clusterConfig.AcRelay, err = strconv.ParseBool(configValue)
   264  		if err != nil {
   265  			return err
   266  		}
   267  	case PxeEnabledKey:
   268  		clusterConfig.PxeEnabled, err = strconv.ParseBool(configValue)
   269  		if err != nil {
   270  			return err
   271  		}
   272  	case BootstrapAckKey:
   273  		clusterConfig.BootstrapAck, err = strconv.ParseBool(configValue)
   274  		if err != nil {
   275  			return err
   276  		}
   277  	case VpnEnabledKey:
   278  		clusterConfig.VpnEnabled, err = strconv.ParseBool(configValue)
   279  		if err != nil {
   280  			return err
   281  		}
   282  	case ThickPosKey:
   283  		clusterConfig.ThickPos, err = strconv.ParseBool(configValue)
   284  		if err != nil {
   285  			return err
   286  		}
   287  	case EgressGatewayEnabledKey:
   288  		clusterConfig.EgressGatewayEnabled, err = strconv.ParseBool(configValue)
   289  		if err != nil {
   290  			return err
   291  		}
   292  	case GatewayRateLimitingEnabledKey:
   293  		clusterConfig.GatewayRateLimitingEnabled, err = strconv.ParseBool(configValue)
   294  		if err != nil {
   295  			return err
   296  		}
   297  	case UplinkRateLimitKey:
   298  		clusterConfig.UplinkRateLimit = configValue
   299  	case DownlinkRateLimitKey:
   300  		clusterConfig.DownlinkRateLimit = configValue
   301  	case ClusterLogLevelKey:
   302  		clusterConfig.ClusterLogLevel = configValue
   303  	case NamespaceLogLevelsKey:
   304  		convertedPayload, err := mapper.JSONtoNLL(configValue)
   305  		if err != nil {
   306  			return err
   307  		}
   308  		clusterConfig.NamespaceLogLevels = convertedPayload
   309  	case MaximumLanOutageHoursKey:
   310  		v, err := strconv.ParseInt(configValue, 10, 64)
   311  		if err != nil {
   312  			return err
   313  		}
   314  		clusterConfig.MaximumLanOutageHours = int(v)
   315  	// TODO: Marked as DEPRECATED. Remove when appropriate
   316  	//nolint:staticcheck // Allow existing usage of deprecated fields
   317  	case constants.LinkerdIdentityIssuerCertDuration:
   318  		v, err := strconv.ParseInt(configValue, 10, 64)
   319  		if err != nil {
   320  			return err
   321  		}
   322  		clusterConfig.LinkerdIdentityIssuerCertDuration = int(v)
   323  	// TODO: Marked as DEPRECATED. Remove when appropriate
   324  	//nolint:staticcheck // Allow existing usage of deprecated fields
   325  	case constants.LinkerdIdentityIssuerCertRenewBefore:
   326  		v, err := strconv.ParseInt(configValue, 10, 64)
   327  		if err != nil {
   328  			return err
   329  		}
   330  		clusterConfig.LinkerdIdentityIssuerCertRenewBefore = int(v)
   331  	case AutoUpdateEnabledKey:
   332  		clusterConfig.AutoUpdateEnabled, err = strconv.ParseBool(configValue)
   333  		if err != nil {
   334  			return err
   335  		}
   336  	case VncReadWriteAuthRequired:
   337  		val, err := strconv.ParseBool(configValue)
   338  		if err != nil {
   339  			return err
   340  		}
   341  		clusterConfig.VncReadWriteAuthRequired = &val
   342  	case VncReadAuthRequired:
   343  		val, err := strconv.ParseBool(configValue)
   344  		if err != nil {
   345  			return err
   346  		}
   347  		clusterConfig.VncReadAuthRequired = &val
   348  	default:
   349  		// Level 1 is Warning
   350  		log := fog.New(fog.WithLevel(1)).WithName("cluster config service")
   351  
   352  		// prevents records with newly added keys from failing API calls
   353  		msg := fmt.Errorf("unknown cluster config key %s", configKey)
   354  		log.Error(msg, "ensure the new key is added to the cluster configuration API")
   355  		return nil
   356  	}
   357  	return nil
   358  }
   359  
   360  // runs validation against ClusterConfig
   361  func validateClusterConfig(cfg *model.ClusterConfig) error {
   362  	if cfg == nil {
   363  		return nil
   364  	}
   365  
   366  	if err := validateRateLimit(&cfg.UplinkRateLimit); err != nil {
   367  		return err
   368  	}
   369  	if err := validateRateLimit(&cfg.DownlinkRateLimit); err != nil {
   370  		return err
   371  	}
   372  
   373  	if err := validateLogLevel(cfg.ClusterLogLevel); err != nil {
   374  		return err
   375  	}
   376  
   377  	if err := validateNamespaceLogLevel(cfg.NamespaceLogLevels); err != nil {
   378  		return err
   379  	}
   380  
   381  	if err := validateMaximumLanOutageHours(cfg.MaximumLanOutageHours); err != nil {
   382  		return err
   383  	}
   384  
   385  	// TODO: Marked as DEPRECATED. Remove when appropriate
   386  	//nolint:staticcheck // Allow existing usage of deprecated fields
   387  	if err := validateLinkerdIdentityIssuerCertTimes(cfg.LinkerdIdentityIssuerCertDuration, cfg.LinkerdIdentityIssuerCertRenewBefore); err != nil {
   388  		return err
   389  	}
   390  
   391  	return nil
   392  }
   393  
   394  // checks that the rate limit is in correct format
   395  // i.e. 1000kbit or 10mbit
   396  func validateRateLimit(rateLimit *string) error {
   397  	if rateLimit == nil {
   398  		return nil
   399  	}
   400  
   401  	rateLimitRegExp, err := regexp.Compile("^[1-9][0-9]*([kK]bit$|[mM]bit$)")
   402  	if err != nil {
   403  		return err
   404  	}
   405  	if !rateLimitRegExp.MatchString(*rateLimit) {
   406  		return ErrInvalidRateLimit
   407  	}
   408  
   409  	return nil
   410  }
   411  
   412  func validateNamespaceLogLevel(namespaceLogLevels []*model.NamespaceLogLevel) error {
   413  	if namespaceLogLevels == nil {
   414  		return nil
   415  	}
   416  	for _, entry := range namespaceLogLevels {
   417  		if err := validateLogLevel(entry.Level); err != nil {
   418  			return err
   419  		}
   420  	}
   421  	return nil
   422  }
   423  
   424  // checks that the entered log level is valid and exists
   425  func validateLogLevel(level string) error {
   426  	levelExists := slices.Contains(validClusterLogLevels, strings.ToUpper(level))
   427  	if !levelExists {
   428  		return &ErrInvalidLogLevel{LogLevel: level}
   429  	}
   430  	return nil
   431  }
   432  
   433  // Deprecated: Marked as DEPRECATED. Do not use
   434  // checks that the linkerd identity issuer certificate duration is greater than the renewBefore time
   435  func validateLinkerdIdentityIssuerCertTimes(duration, renewBefore int) error {
   436  	if duration <= 0 || renewBefore <= 0 {
   437  		return topology.ErrInvalidCertificateDurationOrRenewBefore
   438  	}
   439  	if duration <= renewBefore {
   440  		return topology.ErrInvalidCertificateRenewBefore
   441  	}
   442  	return nil
   443  }
   444  
   445  func validateMaximumLanOutageHours(maxLanOutageHours int) error {
   446  	if maxLanOutageHours < 24 {
   447  		return ErrInvalidMaximumLanOutageHours
   448  	}
   449  	return nil
   450  }
   451  
   452  // maps UpdateClusterConfig to ClusterConfig
   453  func mapUpdateClusterConfig(clusterCfg *model.ClusterConfig, updateClusterCfg *model.UpdateClusterConfig) {
   454  	if updateClusterCfg.AcRelay != nil {
   455  		clusterCfg.AcRelay = *updateClusterCfg.AcRelay
   456  	}
   457  	if updateClusterCfg.BootstrapAck != nil {
   458  		clusterCfg.BootstrapAck = *updateClusterCfg.BootstrapAck
   459  	}
   460  	if updateClusterCfg.VpnEnabled != nil {
   461  		clusterCfg.VpnEnabled = *updateClusterCfg.VpnEnabled
   462  	}
   463  	if updateClusterCfg.PxeEnabled != nil {
   464  		clusterCfg.PxeEnabled = *updateClusterCfg.PxeEnabled
   465  	}
   466  	if updateClusterCfg.ThickPos != nil {
   467  		clusterCfg.ThickPos = *updateClusterCfg.ThickPos
   468  	}
   469  	if updateClusterCfg.EgressGatewayEnabled != nil {
   470  		clusterCfg.EgressGatewayEnabled = *updateClusterCfg.EgressGatewayEnabled
   471  	}
   472  	if updateClusterCfg.GatewayRateLimitingEnabled != nil {
   473  		clusterCfg.GatewayRateLimitingEnabled = *updateClusterCfg.GatewayRateLimitingEnabled
   474  	}
   475  	if updateClusterCfg.UplinkRateLimit != nil {
   476  		clusterCfg.UplinkRateLimit = *updateClusterCfg.UplinkRateLimit
   477  	}
   478  	if updateClusterCfg.DownlinkRateLimit != nil {
   479  		clusterCfg.DownlinkRateLimit = *updateClusterCfg.DownlinkRateLimit
   480  	}
   481  	if updateClusterCfg.ClusterLogLevel != nil {
   482  		clusterCfg.ClusterLogLevel = *updateClusterCfg.ClusterLogLevel
   483  	}
   484  	if updateClusterCfg.NamespaceLogLevels != nil {
   485  		convertedNamespaceLogLevel := mapper.NLLPToNLL(updateClusterCfg.NamespaceLogLevels)
   486  		clusterCfg.NamespaceLogLevels = convertedNamespaceLogLevel
   487  	}
   488  	if updateClusterCfg.MaximumLanOutageHours != nil {
   489  		clusterCfg.MaximumLanOutageHours = *updateClusterCfg.MaximumLanOutageHours
   490  	}
   491  	// TODO: Marked as DEPRECATED. Remove when appropriate
   492  	//nolint:staticcheck // Allow existing usage of deprecated fields
   493  	if updateClusterCfg.LinkerdIdentityIssuerCertDuration != nil {
   494  		clusterCfg.LinkerdIdentityIssuerCertDuration = *updateClusterCfg.LinkerdIdentityIssuerCertDuration
   495  	}
   496  	// TODO: Marked as DEPRECATED. Remove when appropriate
   497  	//nolint:staticcheck // Allow existing usage of deprecated fields
   498  	if updateClusterCfg.LinkerdIdentityIssuerCertRenewBefore != nil {
   499  		clusterCfg.LinkerdIdentityIssuerCertRenewBefore = *updateClusterCfg.LinkerdIdentityIssuerCertRenewBefore
   500  	}
   501  	if updateClusterCfg.AutoUpdateEnabled != nil {
   502  		clusterCfg.AutoUpdateEnabled = *updateClusterCfg.AutoUpdateEnabled
   503  	}
   504  	if updateClusterCfg.VncReadWriteAuthRequired != nil {
   505  		clusterCfg.VncReadWriteAuthRequired = updateClusterCfg.VncReadWriteAuthRequired
   506  	}
   507  	if updateClusterCfg.VncReadAuthRequired != nil {
   508  		clusterCfg.VncReadAuthRequired = updateClusterCfg.VncReadAuthRequired
   509  	}
   510  }
   511  
   512  // returns default settings for ClusterConfig struct
   513  func defaultClusterConfig(clusterEdgeID string) *model.ClusterConfig {
   514  	return &model.ClusterConfig{
   515  		ClusterEdgeID:              clusterEdgeID,
   516  		AcRelay:                    false,
   517  		VpnEnabled:                 false,
   518  		BootstrapAck:               true,
   519  		PxeEnabled:                 false,
   520  		ThickPos:                   true,
   521  		EgressGatewayEnabled:       false,
   522  		GatewayRateLimitingEnabled: false,
   523  		UplinkRateLimit:            defaultRateLimit,
   524  		DownlinkRateLimit:          defaultRateLimit,
   525  		ClusterLogLevel:            logLevelDefault,
   526  		NamespaceLogLevels:         make([]*model.NamespaceLogLevel, 0),
   527  		MaximumLanOutageHours:      int(linkerd.DefaultThinPosIdentityIssuerCertificateDurationHours),
   528  		// TODO: Marked as DEPRECATED. Remove
   529  		LinkerdIdentityIssuerCertDuration:    int(linkerd.DefaultThinPosIdentityIssuerCertificateDurationHours),
   530  		LinkerdIdentityIssuerCertRenewBefore: int(linkerd.DefaultThinPosIdentityIssuerCertificateRenewBeforeHours),
   531  		VncReadWriteAuthRequired:             nil,
   532  		VncReadAuthRequired:                  nil,
   533  	}
   534  }
   535  

View as plain text