controller

package
v0.64.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: Apache-2.0 Imports: 37 Imported by: 0

Documentation

Index

Constants

View Source
const SyncSetName = "pull-secret-update"

SyncSetName is the name used by this tool for pull secret SyncSets. Distinct from "pull-secret-replacement" used by transfer-owner to avoid collisions.

Variables

View Source
var CRSecretPollInterval = 5 * time.Second

CRSecretPollInterval is the delay between CR health checks after deleting a secret.

View Source
var CRSecretPollTimeout = 60 * time.Second

CRSecretPollTimeout is the maximum time to wait for CCO to recreate a secret.

View Source
var RequiredPullSecretAuths = []string{
	"cloud.openshift.com",
	"quay.io",
	"registry.redhat.io",
	"registry.connect.redhat.com",
}

RequiredPullSecretAuths lists the registry auth entries that must be present in a cluster's pull secret for the cluster to function.

View Source
var RotationRequiredActions = []string{
	"iam:CreateAccessKey",
	"iam:CreateUser",
	"iam:DeleteAccessKey",
	"iam:DeleteUser",
	"iam:DeleteUserPolicy",
	"iam:GetUser",
	"iam:GetUserPolicy",
	"iam:ListAccessKeys",
	"iam:PutUserPolicy",
	"iam:TagUser",
}

RotationRequiredActions are the IAM actions needed by the rotation tooling to create/delete access keys and manage IAM users.

View Source
var SyncMaxRetries = 6

SyncMaxRetries is the maximum number of ClusterSync poll attempts.

View Source
var SyncPollInterval = 5 * time.Second

SyncPollInterval is the delay between ClusterSync status checks.

Functions

func AccessTokenToSimple added in v0.63.0

func AccessTokenToSimple(auths map[string]*amv1.AccessTokenAuth) map[string]SimpleAuth

AccessTokenToSimple converts access token auths to SimpleAuth map.

func CheckExistingSyncSets added in v0.63.0

func CheckExistingSyncSets(ctx context.Context, hiveNamespace string, kubeCli client.Client, in io.Reader, out io.Writer) error

CheckExistingSyncSets checks for existing SyncSets that could interfere with a new pull secret sync. Must be called BEFORE updating the hive secret so that aborting leaves no mutations.

func CountOwnerClusters added in v0.63.0

func CountOwnerClusters(ocm *sdk.Connection, accountID string, logger *logrus.Logger) int

CountOwnerClusters returns the number of active clusters owned by the given account ID.

func DeleteCredentialSecrets added in v0.62.0

func DeleteCredentialSecrets(ctx context.Context, managedClient client.Client, in io.Reader, out io.Writer) error

DeleteCredentialSecrets sequentially deletes each credential secret and waits for CCO to recreate it before proceeding to the next one.

func ExtractRegistryAuth added in v0.63.0

func ExtractRegistryAuth(pullSecretData []byte, registry string) (string, error)

ExtractRegistryAuth extracts the "auth" field for a given registry from raw pull secret JSON bytes.

func FetchOwnerAccessToken added in v0.63.0

func FetchOwnerAccessToken(ocm *sdk.Connection, ownerUsername string, logger *logrus.Logger) ([]byte, map[string]*amv1.AccessTokenAuth, error)

FetchOwnerAccessToken retrieves the cluster owner's pull secret from OCM, using impersonation if the current OCM user is not the cluster owner. Returns the marshaled pull secret bytes and the raw auth map for verification.

func GetLatestCredentialUpdate added in v0.63.0

func GetLatestCredentialUpdate(ocm *sdk.Connection, accountID string) (time.Time, error)

GetLatestCredentialUpdate returns the most recent UpdatedAt time across all registry credentials for the given account.

func MergePullSecretAuths added in v0.63.0

func MergePullSecretAuths(existingData, newData []byte) ([]byte, error)

MergePullSecretAuths merges new auths into existing pull secret data. Existing auths not present in newData are preserved. This never removes auths.

func RenderCredRequestTable added in v0.62.0

func RenderCredRequestTable(report *DiagnosticReport, out io.Writer)

RenderCredRequestTable outputs the CredentialRequest secrets table.

func RenderReport added in v0.62.0

func RenderReport(report *DiagnosticReport, out io.Writer)

RenderReport formats the diagnostic report as a human-readable table.

func RenderThreeWayComparison added in v0.63.0

func RenderThreeWayComparison(result *ThreeWayComparison, sourceLabel string, hasHive bool, out io.Writer)

RenderThreeWayComparison prints the three-way comparison in a readable format. sourceLabel identifies the OCM source (e.g. "ACCESS TOKEN AUTHS", "REGISTRY CREDENTIAL AUTHS"). When hasHive is false (HCP clusters), the hive columns are omitted.

func RenderVerifyResult added in v0.63.0

func RenderVerifyResult(result *PullSecretVerifyResult, out io.Writer)

RenderVerifyResult writes the verification result in human-readable format.

func RestartPodsBySelector added in v0.63.0

func RestartPodsBySelector(ctx context.Context, clientset *kubernetes.Clientset, namespace, selector string, out io.Writer) error

RestartPodsBySelector deletes pods matching the selector in the namespace to trigger a rollout.

func RotateSecret

func RotateSecret(ctx context.Context, input *RotateSecretInput) error

RotateSecret performs the IAM credential rotation workflow:

  1. Validates the Account CR (not STS, has iamUserId label)
  2. Resolves the osdManagedAdmin username
  3. Verifies rotation permissions via SimulatePrincipalPolicy
  4. Creates a new IAM access key
  5. Updates k8s secrets on hive
  6. Creates a SyncSet to push credentials to the cluster
  7. Polls ClusterSync for completion and cleans up the SyncSet
  8. Optionally rotates osdCcsAdmin credentials

func UpdateHCPPullSecretViaManifestWork added in v0.63.0

func UpdateHCPPullSecretViaManifestWork(ctx context.Context, ocm *sdk.Connection, kubeCli client.Client, clusterID, mgmtClusterName string, pullsecret []byte, in io.Reader, out io.Writer) error

UpdateHCPPullSecretViaManifestWork updates the pull secret within a ManifestWork on the service cluster for HCP clusters.

HCP pull secret architecture:

func UpdateHivePullSecretSSS added in v0.63.0

func UpdateHivePullSecretSSS(ctx context.Context, kubeCli client.Client, clientset kubernetes.Interface, hiveNamespace string, cdName string, pullsecret []byte, in io.Reader, out io.Writer) error

UpdateHivePullSecretSSS updates the pull secret in the given hive namespace using update-in-place (never deletes). If the secret doesn't exist, it creates it. When the secret exists, new auths are merged into the existing secret via MergePullSecretAuths, preserving any auths not present in the new data.

func ValidateRequiredAuths added in v0.63.0

func ValidateRequiredAuths(auths map[string]*amv1.AccessTokenAuth) []string

ValidateRequiredAuths checks that the OCM access token includes all required registry auth entries. Returns the list of missing registries.

func VerifyRotationPermissions

func VerifyRotationPermissions(out io.Writer, awsClient awsprovider.Client, accountID string, username string) error

VerifyRotationPermissions checks if the assumed role has the necessary IAM permissions to perform secret rotation by simulating the required actions. Uses simulateActions internally for consistency with the diagnostic path.

Types

type AWSCredsInput added in v0.62.0

type AWSCredsInput struct {
	ClusterID         string
	ClusterName       string
	ClusterExternalID string
	IsCCS             bool
	AWSAccountID      string
	AccountCRName     string
	Account           *awsv1alpha1.Account
	AdminUsername     string
	AwsClient         awsprovider.Client
	HiveKubeClient    client.Client
	ManagedClient     client.Client
	Log               *logrus.Logger
	Out               io.Writer
}

AWSCredsInput holds all resolved dependencies needed for both diagnostics and rotation. The CLI layer resolves AWS and k8s clients before calling DiagnoseCredentials or RotateCredentials.

type AuthCheckResult added in v0.63.0

type AuthCheckResult struct {
	Registry   string
	Source     string // "access_token" or "registry_credential"
	OK         bool
	TokenMatch bool
	EmailMatch bool
	Email      string
	Detail     string
}

AuthCheckResult holds the outcome of a single registry auth comparison.

type ClusterSummary added in v0.63.0

type ClusterSummary struct {
	Name      string
	ID        string
	Status    string
	CreatedAt time.Time
}

ClusterSummary holds subscription-level data for a cluster owned by an account.

func ListOwnerSubscriptions added in v0.63.0

func ListOwnerSubscriptions(ocm *sdk.Connection, accountID string) ([]ClusterSummary, error)

ListOwnerSubscriptions returns all active subscriptions for the given account ID.

type CredRequestStatus added in v0.62.0

type CredRequestStatus struct {
	CredRequestName string
	SecretName      string
	Namespace       string
	Age             time.Duration
	Exists          bool
	NeedsRecreation bool
	ErrorMessage    string
}

type DiagnosticReport added in v0.62.0

type DiagnosticReport struct {
	ClusterID         string
	ClusterName       string
	ClusterExternalID string
	IsCCS             bool
	AWSAccountID      string
	AccountCRName     string

	ManagedAdminUser string
	CcsAdminUser     string
	CallerARN        string
	CallerAccount    string

	Keys         []KeyStatus
	Secrets      []SecretStatus
	CredRequests []CredRequestStatus
	Permissions  []PermissionResult
	Findings     []Finding

	AllPermissionsOK bool
	AllSecretsInSync bool
	RootKeyInSync    bool
	ClusterRootKeyID string
	HiveAccountKeyID string
}

func DiagnoseCRSecrets added in v0.62.0

func DiagnoseCRSecrets(ctx context.Context, hiveClient client.Client, managedClient client.Client, accountCRName string, account *awsv1alpha1.Account, out io.Writer) (*DiagnosticReport, error)

DiagnoseCRSecrets produces a lightweight report of just the CredentialRequest secrets, comparing the cluster's root credential (kube-system/aws-creds) against the Hive account secret to detect staleness.

func DiagnoseCredentials added in v0.62.0

func DiagnoseCredentials(ctx context.Context, input *AWSCredsInput) (*DiagnosticReport, error)

DiagnoseCredentials runs a full read-only diagnostic of IAM keys, Hive secrets, CredentialRequests, and IAM permissions, returning a structured report.

type Finding added in v0.62.0

type Finding struct {
	Severity string // "OK", "WARN", "FAIL"
	Message  string
	Guidance string
}

type HiveNamespaceInfo added in v0.63.0

type HiveNamespaceInfo struct {
	Namespace             string
	ClusterDeploymentName string
}

HiveNamespaceInfo holds the resolved Hive namespace and ClusterDeployment name for a given cluster.

func FindHiveNamespace added in v0.63.0

func FindHiveNamespace(ctx context.Context, kubeCli client.Client, clusterID string) (*HiveNamespaceInfo, error)

FindHiveNamespace discovers the Hive namespace for a cluster by listing ClusterDeployments filtered by the api.openshift.com/id label. This avoids the fragile uhc-{env}-{clusterID} namespace construction.

type InsufficientPermissionsError

type InsufficientPermissionsError struct {
	DeniedActions []string
}

InsufficientPermissionsError is returned when SimulatePrincipalPolicy reports that one or more required IAM actions are denied.

func (*InsufficientPermissionsError) Error

Error returns a human-readable message listing the denied IAM actions.

type KeyStatus added in v0.62.0

type KeyStatus struct {
	UserName    string
	AccessKeyID string
	Age         time.Duration
	CreateDate  time.Time
	LastUsed    string
	Status      string
	HiveMatch   bool
}

type PermissionResult added in v0.62.0

type PermissionResult struct {
	Action      string
	Allowed     bool
	Category    string   // "rotation" or "credreq"
	RequestedBy []string // CR names that request this action (credreq category only)
}

type PullSecretOp added in v0.63.0

type PullSecretOp struct {
	DryRun             bool
	Logger             *logrus.Logger
	Out                io.Writer
	AllOK              bool
	PullSecretUpToDate bool
	PullSecretUpdated  bool
	AuthDiffCount      int
	Failures           []string
}

PullSecretOp carries context for pull secret operations. Each method checks DryRun and either performs the operation or reports what it would do.

func NewPullSecretOp added in v0.63.0

func NewPullSecretOp(dryRun bool, logger *logrus.Logger, out io.Writer) *PullSecretOp

NewPullSecretOp creates a new operation context.

func (*PullSecretOp) CheckCanI added in v0.63.0

func (op *PullSecretOp) CheckCanI(ctx context.Context, clientset *kubernetes.Clientset, systemLabel, verb, resource, group, namespace string) bool

CheckCanI verifies RBAC permission. In dry-run mode it reports the result. In live mode it just logs the check. Returns whether the permission is allowed.

func (*PullSecretOp) CheckSecretExists added in v0.63.0

func (op *PullSecretOp) CheckSecretExists(ctx context.Context, clientset *kubernetes.Clientset, namespace, name, systemLabel string) bool

CheckSecretExists checks if a secret exists. Returns true if found.

func (*PullSecretOp) Fail added in v0.63.0

func (op *PullSecretOp) Fail(format string, args ...any)

Fail prints a failure result and marks the operation as not-all-OK.

func (*PullSecretOp) FetchAccessTokenOp added in v0.63.0

func (op *PullSecretOp) FetchAccessTokenOp(ocm *sdk.Connection, ownerUsername string) ([]byte, map[string]*amv1.AccessTokenAuth, bool)

FetchAccessTokenOp wraps FetchOwnerAccessToken with operational output.

func (*PullSecretOp) FindHiveNamespaceOp added in v0.63.0

func (op *PullSecretOp) FindHiveNamespaceOp(ctx context.Context, kubeCli client.Client, clusterID, infraName string) (*HiveNamespaceInfo, bool)

FindHiveNamespaceOp wraps FindHiveNamespace with operational output.

func (*PullSecretOp) Info added in v0.63.0

func (op *PullSecretOp) Info(format string, args ...any)

Info prints an informational message.

func (*PullSecretOp) OK added in v0.63.0

func (op *PullSecretOp) OK(format string, args ...any)

OK prints a success result.

func (*PullSecretOp) ResolveExistingPullSecret added in v0.63.0

func (op *PullSecretOp) ResolveExistingPullSecret(ctx context.Context, infraClientSet *kubernetes.Clientset, targetClientSet *kubernetes.Clientset, hiveNS string, infraName string, targetName string) ([]byte, string)

ResolveExistingPullSecret finds the best available base pull secret data. Tries the hive secret first, then falls back to the target cluster's secret. Returns the secret data bytes and the source description.

func (*PullSecretOp) Section added in v0.63.0

func (op *PullSecretOp) Section(step int, title string, lines ...string)

Section prints a step header with educational description.

func (*PullSecretOp) Warn added in v0.63.0

func (op *PullSecretOp) Warn(format string, args ...any)

Warn prints a warning.

func (*PullSecretOp) Would added in v0.63.0

func (op *PullSecretOp) Would(format string, args ...any)

Would prints what the operation would do (dry-run only).

type PullSecretVerifyResult added in v0.63.0

type PullSecretVerifyResult struct {
	Matched         int
	Total           int
	Mismatches      []string
	AuthResults     []AuthCheckResult
	MissingRequired []string
}

PullSecretVerifyResult holds the outcome of a per-registry auth comparison.

func CompareAccessTokenAuthsToCluster added in v0.63.0

func CompareAccessTokenAuthsToCluster(ctx context.Context, clientset *kubernetes.Clientset, expectedAuths map[string]*amv1.AccessTokenAuth, out io.Writer) (*PullSecretVerifyResult, error)

CompareAccessTokenAuthsToCluster compares OCM access token auths against the pull secret on the target cluster. Writes per-registry results to out. Returns a PullSecretVerifyResult with match counts and any mismatches.

func CompareRegistryCredentialAuthsToCluster added in v0.63.0

func CompareRegistryCredentialAuthsToCluster(ctx context.Context, ocm *sdk.Connection, clientset *kubernetes.Clientset, accountID string, accountEmail string, out io.Writer) (*PullSecretVerifyResult, error)

CompareRegistryCredentialAuthsToCluster compares OCM registry credentials against the pull secret on the target cluster. Registry credentials use a different token format (base64-encoded "username:token") than access token auths.

type RotateSecretInput

type RotateSecretInput struct {
	// AccountCRName is the name of the Account CR.
	AccountCRName string

	// Account is the pre-fetched Account CR.
	Account *awsv1alpha1.Account

	// OsdManagedAdminUsername is an explicit admin username override.
	// If empty, it is derived from the Account CR's iamUserId label.
	OsdManagedAdminUsername string

	// UpdateManagedAdminCreds controls whether osdManagedAdmin credentials are rotated.
	UpdateManagedAdminCreds bool

	// UpdateCcsCreds controls whether osdCcsAdmin credentials are also rotated.
	UpdateCcsCreds bool

	// AwsClient is the fully-authenticated AWS client with permissions in the
	// target AWS account (after all role chaining has been completed).
	AwsClient awsprovider.Client

	// HiveKubeClient is the k8s client connected to the hive cluster.
	HiveKubeClient client.Client

	// ManagedClusterClient is the k8s client connected to the managed cluster
	// (via backplane using the target OCM environment). Used to delete
	// CredentialRequests so CCO recreates them with the new credentials.
	ManagedClusterClient client.Client

	// DryRun, when true, prints what actions would be taken without performing
	// any mutating operations (no AWS key creation/deletion, no k8s resource
	// creation/deletion/updates).
	DryRun bool

	// Report is the pre-computed diagnostic report from the snapshot phase.
	// Used to display key/secret context during interactive key deletion.
	Report *DiagnosticReport

	// Log is the logger for operational messages (writes to stderr).
	Log *logrus.Logger

	// SkipPermissionCheck skips the managed-admin permission verification when
	// the caller has already run diagnostics and the user confirmed despite failures.
	SkipPermissionCheck bool

	// In is the reader for interactive prompts (defaults to os.Stdin).
	In io.Reader

	// Out is the writer for structured report output (writes to stdout).
	Out io.Writer
}

RotateSecretInput holds all resolved dependencies for secret rotation. The CLI layer is responsible for resolving AWS and k8s clients before calling RotateSecret.

type SecretStatus added in v0.62.0

type SecretStatus struct {
	SecretName   string
	Namespace    string
	AccessKeyID  string
	MatchesAWS   bool
	Exists       bool
	ErrorMessage string
}

type SimpleAuth added in v0.63.0

type SimpleAuth struct {
	Auth  string
	Email string
}

SimpleAuth holds a registry auth's token and email for generic comparison.

type ThreeWayAuthState added in v0.63.0

type ThreeWayAuthState struct {
	Registry          string
	InOCM             bool
	InHive            bool
	InTarget          bool
	OCMMatchesHive    bool
	OCMMatchesTarget  bool
	HiveMatchesTarget bool
}

ThreeWayAuthState describes the sync state of a single auth entry across OCM, hive, and target.

type ThreeWayComparison added in v0.63.0

type ThreeWayComparison struct {
	Auths           []ThreeWayAuthState
	HiveNeedsUpdate bool
	TargetNeedsSync bool
	AllInSync       bool
}

ThreeWayComparison holds the full comparison result across OCM, hive, and target.

func CompareThreeWay added in v0.63.0

func CompareThreeWay(ocmAuths map[string]SimpleAuth, hiveData []byte, targetData []byte) (*ThreeWayComparison, error)

CompareThreeWay compares pull secret auths across OCM, hive secret, and target cluster secret. ocmAuths maps registry name → SimpleAuth with the expected auth/email values. hiveData and targetData are the raw .dockerconfigjson bytes from each secret.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL